aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs9
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCapsModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs96
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs446
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs190
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs117
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs6
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs7
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs198
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs468
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs101
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs306
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs7
23 files changed, 1733 insertions, 304 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 650cd50..f6146a9 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -241,8 +241,8 @@ namespace OpenSim.Region.ClientStack.Linden
241 m_HostCapsObj.RegisterHandler( 241 m_HostCapsObj.RegisterHandler(
242 "SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null)); 242 "SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null));
243 243
244 m_log.DebugFormat( 244// m_log.DebugFormat(
245 "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID); 245// "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID);
246 246
247 //m_capsHandlers["MapLayer"] = 247 //m_capsHandlers["MapLayer"] =
248 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST", 248 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST",
@@ -337,11 +337,12 @@ namespace OpenSim.Region.ClientStack.Linden
337 public string SeedCapRequest(string request, string path, string param, 337 public string SeedCapRequest(string request, string path, string param,
338 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 338 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
339 { 339 {
340// m_log.Debug("[CAPS]: Seed Caps Request in region: " + m_regionName); 340 m_log.DebugFormat(
341 "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID);
341 342
342 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint)) 343 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint))
343 { 344 {
344 m_log.DebugFormat( 345 m_log.WarnFormat(
345 "[CAPS]: Unauthorized CAPS client {0} from {1}", 346 "[CAPS]: Unauthorized CAPS client {0} from {1}",
346 m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint); 347 m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint);
347 348
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCapsModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCapsModule.cs
index 66b865f..b735dfa 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCapsModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCapsModule.cs
@@ -45,7 +45,7 @@ using Caps = OpenSim.Framework.Capabilities.Caps;
45namespace OpenSim.Region.ClientStack.Linden 45namespace OpenSim.Region.ClientStack.Linden
46{ 46{
47 47
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BunchOfCapsModule")]
49 public class BunchOfCapsModule : INonSharedRegionModule 49 public class BunchOfCapsModule : INonSharedRegionModule
50 { 50 {
51// private static readonly ILog m_log = 51// private static readonly ILog m_log =
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index e113c60..986a665 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -55,8 +55,8 @@ namespace OpenSim.Region.ClientStack.Linden
55 public OSDMap body; 55 public OSDMap body;
56 } 56 }
57 57
58 //[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 58 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EventQueueGetModule")]
59 public class EventQueueGetModule : IEventQueue, IRegionModule 59 public class EventQueueGetModule : IEventQueue, INonSharedRegionModule
60 { 60 {
61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
62 62
@@ -66,8 +66,6 @@ namespace OpenSim.Region.ClientStack.Linden
66 public int DebugLevel { get; set; } 66 public int DebugLevel { get; set; }
67 67
68 protected Scene m_scene; 68 protected Scene m_scene;
69 private IConfigSource m_gConfig;
70 bool enabledYN;
71 69
72 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>(); 70 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>();
73 71
@@ -75,59 +73,46 @@ namespace OpenSim.Region.ClientStack.Linden
75 private Dictionary<UUID, UUID> m_QueueUUIDAvatarMapping = new Dictionary<UUID, UUID>(); 73 private Dictionary<UUID, UUID> m_QueueUUIDAvatarMapping = new Dictionary<UUID, UUID>();
76 private Dictionary<UUID, UUID> m_AvatarQueueUUIDMapping = new Dictionary<UUID, UUID>(); 74 private Dictionary<UUID, UUID> m_AvatarQueueUUIDMapping = new Dictionary<UUID, UUID>();
77 75
78 #region IRegionModule methods 76 #region INonSharedRegionModule methods
79 public virtual void Initialise(Scene scene, IConfigSource config) 77 public virtual void Initialise(IConfigSource config)
80 { 78 {
81 m_gConfig = config; 79 }
82 80
83 IConfig startupConfig = m_gConfig.Configs["Startup"]; 81 public void AddRegion(Scene scene)
82 {
83 m_scene = scene;
84 scene.RegisterModuleInterface<IEventQueue>(this);
84 85
85 ReadConfigAndPopulate(scene, startupConfig, "Startup"); 86 scene.EventManager.OnClientClosed += ClientClosed;
87 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
88 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
86 89
87 if (enabledYN) 90 MainConsole.Instance.Commands.AddCommand(
88 { 91 "Debug",
89 m_scene = scene; 92 false,
90 scene.RegisterModuleInterface<IEventQueue>(this); 93 "debug eq",
91 94 "debug eq [0|1|2]",
92 // Register fallback handler 95 "Turn on event queue debugging\n"
93 // Why does EQG Fail on region crossings! 96 + " <= 0 - turns off all event queue logging\n"
94 97 + " >= 1 - turns on outgoing event logging\n"
95 //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack); 98 + " >= 2 - turns on poll notification",
96 99 HandleDebugEq);
97 scene.EventManager.OnNewClient += OnNewClient;
98
99 // TODO: Leaving these open, or closing them when we
100 // become a child is incorrect. It messes up TP in a big
101 // way. CAPS/EQ need to be active as long as the UDP
102 // circuit is there.
103
104 scene.EventManager.OnClientClosed += ClientClosed;
105 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
106 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
107
108 MainConsole.Instance.Commands.AddCommand(
109 "Debug",
110 false,
111 "debug eq",
112 "debug eq [0|1|2]",
113 "Turn on event queue debugging"
114 + "<= 0 - turns off all event queue logging"
115 + ">= 1 - turns on outgoing event logging"
116 + ">= 2 - turns on poll notification",
117 HandleDebugEq);
118 }
119 else
120 {
121 m_gConfig = null;
122 }
123 } 100 }
124 101
125 private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string p) 102 public void RemoveRegion(Scene scene)
126 { 103 {
127 enabledYN = startupConfig.GetBoolean("EventQueue", true); 104 if (m_scene != scene)
105 return;
106
107 scene.EventManager.OnClientClosed -= ClientClosed;
108 scene.EventManager.OnMakeChildAgent -= MakeChildAgent;
109 scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
110
111 scene.UnregisterModuleInterface<IEventQueue>(this);
112 m_scene = null;
128 } 113 }
129 114
130 public void PostInitialise() 115 public void RegionLoaded(Scene scene)
131 { 116 {
132 } 117 }
133 118
@@ -140,10 +125,11 @@ namespace OpenSim.Region.ClientStack.Linden
140 get { return "EventQueueGetModule"; } 125 get { return "EventQueueGetModule"; }
141 } 126 }
142 127
143 public bool IsSharedModule 128 public Type ReplaceableInterface
144 { 129 {
145 get { return false; } 130 get { return null; }
146 } 131 }
132
147 #endregion 133 #endregion
148 134
149 protected void HandleDebugEq(string module, string[] args) 135 protected void HandleDebugEq(string module, string[] args)
@@ -226,16 +212,6 @@ namespace OpenSim.Region.ClientStack.Linden
226 212
227 #endregion 213 #endregion
228 214
229 private void OnNewClient(IClientAPI client)
230 {
231 //client.OnLogout += ClientClosed;
232 }
233
234// private void ClientClosed(IClientAPI client)
235// {
236// ClientClosed(client.AgentId);
237// }
238
239 private void ClientClosed(UUID agentID, Scene scene) 215 private void ClientClosed(UUID agentID, Scene scene)
240 { 216 {
241// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); 217// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
index cd70410..d604cf6 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
@@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
94 UUID spId = TestHelpers.ParseTail(0x1); 94 UUID spId = TestHelpers.ParseTail(0x1);
95 95
96 SceneHelpers.AddScenePresence(m_scene, spId); 96 SceneHelpers.AddScenePresence(m_scene, spId);
97 m_scene.IncomingCloseAgent(spId); 97 m_scene.IncomingCloseAgent(spId, false);
98 98
99 // TODO: Add more assertions for the other aspects of event queues 99 // TODO: Add more assertions for the other aspects of event queues
100 Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); 100 Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0));
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs b/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs
index cb5afcc..87d3d1c 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Region.ClientStack.Linden
45 /// <summary> 45 /// <summary>
46 /// This module implements both WebFetchInventoryDescendents and FetchInventoryDescendents2 capabilities. 46 /// This module implements both WebFetchInventoryDescendents and FetchInventoryDescendents2 capabilities.
47 /// </summary> 47 /// </summary>
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "FetchInventory2Module")]
49 public class FetchInventory2Module : INonSharedRegionModule 49 public class FetchInventory2Module : INonSharedRegionModule
50 { 50 {
51// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
index 0d7b1fc..6b33561 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
@@ -27,11 +27,14 @@
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic;
30using System.Collections.Specialized; 31using System.Collections.Specialized;
31using System.Reflection; 32using System.Reflection;
32using System.IO; 33using System.IO;
34using System.Threading;
33using System.Web; 35using System.Web;
34using Mono.Addins; 36using Mono.Addins;
37using OpenSim.Framework.Monitoring;
35using log4net; 38using log4net;
36using Nini.Config; 39using Nini.Config;
37using OpenMetaverse; 40using OpenMetaverse;
@@ -47,7 +50,7 @@ using Caps = OpenSim.Framework.Capabilities.Caps;
47 50
48namespace OpenSim.Region.ClientStack.Linden 51namespace OpenSim.Region.ClientStack.Linden
49{ 52{
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetMeshModule")]
51 public class GetMeshModule : INonSharedRegionModule 54 public class GetMeshModule : INonSharedRegionModule
52 { 55 {
53// private static readonly ILog m_log = 56// private static readonly ILog m_log =
@@ -57,8 +60,44 @@ namespace OpenSim.Region.ClientStack.Linden
57 private IAssetService m_AssetService; 60 private IAssetService m_AssetService;
58 private bool m_Enabled = true; 61 private bool m_Enabled = true;
59 private string m_URL; 62 private string m_URL;
63
64 struct aPollRequest
65 {
66 public PollServiceMeshEventArgs thepoll;
67 public UUID reqID;
68 public Hashtable request;
69 }
70
71 public class aPollResponse
72 {
73 public Hashtable response;
74 public int bytes;
75 public int lod;
76 }
77
78
79 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
80
81 private static GetMeshHandler m_getMeshHandler;
60 82
61 #region IRegionModuleBase Members 83 private IAssetService m_assetService = null;
84
85 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
86 private static Thread[] m_workerThreads = null;
87
88 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
89 new OpenMetaverse.BlockingQueue<aPollRequest>();
90
91 private Dictionary<UUID, PollServiceMeshEventArgs> m_pollservices = new Dictionary<UUID, PollServiceMeshEventArgs>();
92
93 #region Region Module interfaceBase Members
94
95 ~GetMeshModule()
96 {
97 foreach (Thread t in m_workerThreads)
98 Watchdog.AbortThread(t.ManagedThreadId);
99
100 }
62 101
63 public Type ReplaceableInterface 102 public Type ReplaceableInterface
64 { 103 {
@@ -75,6 +114,7 @@ namespace OpenSim.Region.ClientStack.Linden
75 // Cap doesn't exist 114 // Cap doesn't exist
76 if (m_URL != string.Empty) 115 if (m_URL != string.Empty)
77 m_Enabled = true; 116 m_Enabled = true;
117
78 } 118 }
79 119
80 public void AddRegion(Scene pScene) 120 public void AddRegion(Scene pScene)
@@ -83,6 +123,8 @@ namespace OpenSim.Region.ClientStack.Linden
83 return; 123 return;
84 124
85 m_scene = pScene; 125 m_scene = pScene;
126
127 m_assetService = pScene.AssetService;
86 } 128 }
87 129
88 public void RemoveRegion(Scene scene) 130 public void RemoveRegion(Scene scene)
@@ -91,6 +133,9 @@ namespace OpenSim.Region.ClientStack.Linden
91 return; 133 return;
92 134
93 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 135 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
136 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
137 m_scene.EventManager.OnThrottleUpdate -= ThrottleUpdate;
138
94 m_scene = null; 139 m_scene = null;
95 } 140 }
96 141
@@ -101,6 +146,27 @@ namespace OpenSim.Region.ClientStack.Linden
101 146
102 m_AssetService = m_scene.RequestModuleInterface<IAssetService>(); 147 m_AssetService = m_scene.RequestModuleInterface<IAssetService>();
103 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 148 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
149 // We'll reuse the same handler for all requests.
150 m_getMeshHandler = new GetMeshHandler(m_assetService);
151 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
152 m_scene.EventManager.OnThrottleUpdate += ThrottleUpdate;
153
154 if (m_workerThreads == null)
155 {
156 m_workerThreads = new Thread[2];
157
158 for (uint i = 0; i < 2; i++)
159 {
160 m_workerThreads[i] = Watchdog.StartThread(DoMeshRequests,
161 String.Format("MeshWorkerThread{0}", i),
162 ThreadPriority.Normal,
163 false,
164 false,
165 null,
166 int.MaxValue);
167 }
168 }
169
104 } 170 }
105 171
106 172
@@ -110,25 +176,212 @@ namespace OpenSim.Region.ClientStack.Linden
110 176
111 #endregion 177 #endregion
112 178
179 private void DoMeshRequests()
180 {
181 while (true)
182 {
183 aPollRequest poolreq = m_queue.Dequeue();
184
185 poolreq.thepoll.Process(poolreq);
186 }
187 }
188
189 // Now we know when the throttle is changed by the client in the case of a root agent or by a neighbor region in the case of a child agent.
190 public void ThrottleUpdate(ScenePresence p)
191 {
192 byte[] throttles = p.ControllingClient.GetThrottlesPacked(1);
193 UUID user = p.UUID;
194 int imagethrottle = ExtractTaskThrottle(throttles);
195 PollServiceMeshEventArgs args;
196 if (m_pollservices.TryGetValue(user, out args))
197 {
198 args.UpdateThrottle(imagethrottle, p);
199 }
200 }
201
202 private int ExtractTaskThrottle(byte[] pthrottles)
203 {
204
205 byte[] adjData;
206 int pos = 0;
207
208 if (!BitConverter.IsLittleEndian)
209 {
210 byte[] newData = new byte[7 * 4];
211 Buffer.BlockCopy(pthrottles, 0, newData, 0, 7 * 4);
212
213 for (int i = 0; i < 7; i++)
214 Array.Reverse(newData, i * 4, 4);
215
216 adjData = newData;
217 }
218 else
219 {
220 adjData = pthrottles;
221 }
222
223 // 0.125f converts from bits to bytes
224 //int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
225 //pos += 4;
226 // int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
227 //pos += 4;
228 // int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
229 // pos += 4;
230 // int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
231 // pos += 4;
232 pos += 16;
233 int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
234 // pos += 4;
235 //int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); //pos += 4;
236 //int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
237 return task;
238 }
239
240 private class PollServiceMeshEventArgs : PollServiceEventArgs
241 {
242 private List<Hashtable> requests =
243 new List<Hashtable>();
244 private Dictionary<UUID, aPollResponse> responses =
245 new Dictionary<UUID, aPollResponse>();
246
247 private Scene m_scene;
248 private MeshCapsDataThrottler m_throttler;
249 public PollServiceMeshEventArgs(UUID pId, Scene scene) :
250 base(null, null, null, null, pId, int.MaxValue)
251 {
252 m_scene = scene;
253 m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId);
254 // x is request id, y is userid
255 HasEvents = (x, y) =>
256 {
257 lock (responses)
258 {
259 bool ret = m_throttler.hasEvents(x, responses);
260 m_throttler.ProcessTime();
261 return ret;
262
263 }
264 };
265 GetEvents = (x, y) =>
266 {
267 lock (responses)
268 {
269 try
270 {
271 return responses[x].response;
272 }
273 finally
274 {
275 m_throttler.ProcessTime();
276 responses.Remove(x);
277 }
278 }
279 };
280 // x is request id, y is request data hashtable
281 Request = (x, y) =>
282 {
283 aPollRequest reqinfo = new aPollRequest();
284 reqinfo.thepoll = this;
285 reqinfo.reqID = x;
286 reqinfo.request = y;
287
288 m_queue.Enqueue(reqinfo);
289 };
290
291 // this should never happen except possible on shutdown
292 NoEvents = (x, y) =>
293 {
294 /*
295 lock (requests)
296 {
297 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
298 requests.Remove(request);
299 }
300 */
301 Hashtable response = new Hashtable();
302
303 response["int_response_code"] = 500;
304 response["str_response_string"] = "Script timeout";
305 response["content_type"] = "text/plain";
306 response["keepalive"] = false;
307 response["reusecontext"] = false;
308
309 return response;
310 };
311 }
312
313 public void Process(aPollRequest requestinfo)
314 {
315 Hashtable response;
316
317 UUID requestID = requestinfo.reqID;
318
319 // If the avatar is gone, don't bother to get the texture
320 if (m_scene.GetScenePresence(Id) == null)
321 {
322 response = new Hashtable();
323
324 response["int_response_code"] = 500;
325 response["str_response_string"] = "Script timeout";
326 response["content_type"] = "text/plain";
327 response["keepalive"] = false;
328 response["reusecontext"] = false;
329
330 lock (responses)
331 responses[requestID] = new aPollResponse() { bytes = 0, response = response, lod = 0 };
332
333 return;
334 }
335
336 response = m_getMeshHandler.Handle(requestinfo.request);
337 lock (responses)
338 {
339 responses[requestID] = new aPollResponse()
340 {
341 bytes = (int)response["int_bytes"],
342 lod = (int)response["int_lod"],
343 response = response
344 };
345
346 }
347 m_throttler.ProcessTime();
348 }
349
350 internal void UpdateThrottle(int pimagethrottle, ScenePresence p)
351 {
352 m_throttler.UpdateThrottle(pimagethrottle, p);
353 }
354 }
113 355
114 public void RegisterCaps(UUID agentID, Caps caps) 356 public void RegisterCaps(UUID agentID, Caps caps)
115 { 357 {
116// UUID capID = UUID.Random(); 358// UUID capID = UUID.Random();
117
118 //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture));
119 if (m_URL == "localhost") 359 if (m_URL == "localhost")
120 { 360 {
121// m_log.DebugFormat("[GETMESH]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); 361 string capUrl = "/CAPS/" + UUID.Random() + "/";
122 GetMeshHandler gmeshHandler = new GetMeshHandler(m_AssetService); 362
123 IRequestHandler reqHandler 363 // Register this as a poll service
124 = new RestHTTPHandler( 364 PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(agentID, m_scene);
125 "GET", 365
126 "/CAPS/" + UUID.Random(), 366 args.Type = PollServiceEventArgs.EventType.Mesh;
127 httpMethod => gmeshHandler.ProcessGetMesh(httpMethod, UUID.Zero, null), 367 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
128 "GetMesh",
129 agentID.ToString());
130 368
131 caps.RegisterHandler("GetMesh", reqHandler); 369 string hostName = m_scene.RegionInfo.ExternalHostName;
370 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
371 string protocol = "http";
372
373 if (MainServer.Instance.UseSSL)
374 {
375 hostName = MainServer.Instance.SSLCommonName;
376 port = MainServer.Instance.SSLPort;
377 protocol = "https";
378 }
379 caps.RegisterHandler("GetMesh", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
380 m_pollservices.Add(agentID, args);
381 m_capsDict[agentID] = capUrl;
382
383
384
132 } 385 }
133 else 386 else
134 { 387 {
@@ -136,6 +389,171 @@ namespace OpenSim.Region.ClientStack.Linden
136 caps.RegisterHandler("GetMesh", m_URL); 389 caps.RegisterHandler("GetMesh", m_URL);
137 } 390 }
138 } 391 }
392 private void DeregisterCaps(UUID agentID, Caps caps)
393 {
394 string capUrl;
395 PollServiceMeshEventArgs args;
396 if (m_capsDict.TryGetValue(agentID, out capUrl))
397 {
398 MainServer.Instance.RemoveHTTPHandler("", capUrl);
399 m_capsDict.Remove(agentID);
400 }
401 if (m_pollservices.TryGetValue(agentID, out args))
402 {
403 m_pollservices.Remove(agentID);
404 }
405 }
406
407 internal sealed class MeshCapsDataThrottler
408 {
409
410 private volatile int currenttime = 0;
411 private volatile int lastTimeElapsed = 0;
412 private volatile int BytesSent = 0;
413 private int Lod3 = 0;
414 private int Lod2 = 0;
415 private int Lod1 = 0;
416 private int UserSetThrottle = 0;
417 private int UDPSetThrottle = 0;
418 private int CapSetThrottle = 0;
419 private float CapThrottleDistributon = 0.30f;
420 private readonly Scene m_scene;
421 private ThrottleOutPacketType Throttle;
422 private readonly UUID User;
423
424 public MeshCapsDataThrottler(int pBytes, int max, int min, Scene pScene, UUID puser)
425 {
426 ThrottleBytes = pBytes;
427 lastTimeElapsed = Util.EnvironmentTickCount();
428 Throttle = ThrottleOutPacketType.Task;
429 m_scene = pScene;
430 User = puser;
431 }
432
433
434 public bool hasEvents(UUID key, Dictionary<UUID, aPollResponse> responses)
435 {
436 const float ThirtyPercent = 0.30f;
437 const float FivePercent = 0.05f;
438 PassTime();
439 // Note, this is called IN LOCK
440 bool haskey = responses.ContainsKey(key);
441
442 if (responses.Count > 2)
443 {
444 SplitThrottle(ThirtyPercent);
445 }
446 else
447 {
448 SplitThrottle(FivePercent);
449 }
450
451 if (!haskey)
452 {
453 return false;
454 }
455 aPollResponse response;
456 if (responses.TryGetValue(key, out response))
457 {
458 float LOD3Over = (((ThrottleBytes*CapThrottleDistributon)%50000) + 1);
459 float LOD2Over = (((ThrottleBytes*CapThrottleDistributon)%10000) + 1);
460 // Normal
461 if (BytesSent + response.bytes <= ThrottleBytes)
462 {
463 BytesSent += response.bytes;
464
465 return true;
466 }
467 // Lod3 Over Throttle protection to keep things processing even when the throttle bandwidth is set too little.
468 else if (response.bytes > ThrottleBytes && Lod3 <= ((LOD3Over < 1)? 1: LOD3Over) )
469 {
470 Interlocked.Increment(ref Lod3);
471 BytesSent += response.bytes;
472
473 return true;
474 }
475 // Lod2 Over Throttle protection to keep things processing even when the throttle bandwidth is set too little.
476 else if (response.bytes > ThrottleBytes && Lod2 <= ((LOD2Over < 1) ? 1 : LOD2Over))
477 {
478 Interlocked.Increment(ref Lod2);
479 BytesSent += response.bytes;
480
481 return true;
482 }
483 else
484 {
485 return false;
486 }
487 }
488
489 return haskey;
490 }
491 public void SubtractBytes(int bytes,int lod)
492 {
493 BytesSent -= bytes;
494 }
495 private void SplitThrottle(float percentMultiplier)
496 {
497
498 if (CapThrottleDistributon != percentMultiplier) // don't switch it if it's already set at the % multipler
499 {
500 CapThrottleDistributon = percentMultiplier;
501 ScenePresence p;
502 if (m_scene.TryGetScenePresence(User, out p)) // If we don't get a user they're not here anymore.
503 {
504 AlterThrottle(UserSetThrottle, p);
505 }
506 }
507 }
508
509 public void ProcessTime()
510 {
511 PassTime();
512 }
513
514
515 private void PassTime()
516 {
517 currenttime = Util.EnvironmentTickCount();
518 int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed);
519 //processTimeBasedActions(responses);
520 if (currenttime - timeElapsed >= 1000)
521 {
522 lastTimeElapsed = Util.EnvironmentTickCount();
523 BytesSent -= ThrottleBytes;
524 if (BytesSent < 0) BytesSent = 0;
525 if (BytesSent < ThrottleBytes)
526 {
527 Lod3 = 0;
528 Lod2 = 0;
529 Lod1 = 0;
530 }
531 }
532 }
533 private void AlterThrottle(int setting, ScenePresence p)
534 {
535 p.ControllingClient.SetAgentThrottleSilent((int)Throttle,setting);
536 }
537
538 public int ThrottleBytes
539 {
540 get { return CapSetThrottle; }
541 set { CapSetThrottle = value; }
542 }
543
544 internal void UpdateThrottle(int pimagethrottle, ScenePresence p)
545 {
546 // Client set throttle !
547 UserSetThrottle = pimagethrottle;
548 CapSetThrottle = (int)(pimagethrottle*CapThrottleDistributon);
549 UDPSetThrottle = (int) (pimagethrottle*(100 - CapThrottleDistributon));
550 if (CapSetThrottle < 4068)
551 CapSetThrottle = 4068; // at least two discovery mesh
552 p.ControllingClient.SetAgentThrottleSilent((int) Throttle, UDPSetThrottle);
553 ProcessTime();
554
555 }
556 }
139 557
140 } 558 }
141} 559}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
index d1a1583..dd87671 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
@@ -47,9 +47,6 @@ using OpenSim.Framework.Monitoring;
47namespace OpenSim.Region.ClientStack.Linden 47namespace OpenSim.Region.ClientStack.Linden
48{ 48{
49 49
50 /// <summary>
51 /// This module implements both WebFetchTextureDescendents and FetchTextureDescendents2 capabilities.
52 /// </summary>
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetTextureModule")] 50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetTextureModule")]
54 public class GetTextureModule : INonSharedRegionModule 51 public class GetTextureModule : INonSharedRegionModule
55 { 52 {
@@ -61,6 +58,13 @@ namespace OpenSim.Region.ClientStack.Linden
61 public Hashtable request; 58 public Hashtable request;
62 } 59 }
63 60
61 public class aPollResponse
62 {
63 public Hashtable response;
64 public int bytes;
65 }
66
67
64 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 68 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
65 69
66 private Scene m_scene; 70 private Scene m_scene;
@@ -75,6 +79,8 @@ namespace OpenSim.Region.ClientStack.Linden
75 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue = 79 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
76 new OpenMetaverse.BlockingQueue<aPollRequest>(); 80 new OpenMetaverse.BlockingQueue<aPollRequest>();
77 81
82 private Dictionary<UUID,PollServiceTextureEventArgs> m_pollservices = new Dictionary<UUID,PollServiceTextureEventArgs>();
83
78 #region ISharedRegionModule Members 84 #region ISharedRegionModule Members
79 85
80 public void Initialise(IConfigSource source) 86 public void Initialise(IConfigSource source)
@@ -91,6 +97,7 @@ namespace OpenSim.Region.ClientStack.Linden
91 { 97 {
92 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 98 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
93 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps; 99 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
100 m_scene.EventManager.OnThrottleUpdate -= ThrottleUpdate;
94 m_scene = null; 101 m_scene = null;
95 } 102 }
96 103
@@ -101,6 +108,7 @@ namespace OpenSim.Region.ClientStack.Linden
101 108
102 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 109 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
103 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps; 110 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
111 m_scene.EventManager.OnThrottleUpdate += ThrottleUpdate;
104 112
105 if (m_workerThreads == null) 113 if (m_workerThreads == null)
106 { 114 {
@@ -118,6 +126,56 @@ namespace OpenSim.Region.ClientStack.Linden
118 } 126 }
119 } 127 }
120 } 128 }
129 private int ExtractImageThrottle(byte[] pthrottles)
130 {
131
132 byte[] adjData;
133 int pos = 0;
134
135 if (!BitConverter.IsLittleEndian)
136 {
137 byte[] newData = new byte[7 * 4];
138 Buffer.BlockCopy(pthrottles, 0, newData, 0, 7 * 4);
139
140 for (int i = 0; i < 7; i++)
141 Array.Reverse(newData, i * 4, 4);
142
143 adjData = newData;
144 }
145 else
146 {
147 adjData = pthrottles;
148 }
149
150 // 0.125f converts from bits to bytes
151 //int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
152 //pos += 4;
153 // int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
154 //pos += 4;
155 // int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
156 // pos += 4;
157 // int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
158 // pos += 4;
159 // int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
160 // pos += 4;
161 pos = pos + 20;
162 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); //pos += 4;
163 //int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
164 return texture;
165 }
166
167 // Now we know when the throttle is changed by the client in the case of a root agent or by a neighbor region in the case of a child agent.
168 public void ThrottleUpdate(ScenePresence p)
169 {
170 byte[] throttles = p.ControllingClient.GetThrottlesPacked(1);
171 UUID user = p.UUID;
172 int imagethrottle = ExtractImageThrottle(throttles);
173 PollServiceTextureEventArgs args;
174 if (m_pollservices.TryGetValue(user,out args))
175 {
176 args.UpdateThrottle(imagethrottle);
177 }
178 }
121 179
122 public void PostInitialise() 180 public void PostInitialise()
123 { 181 {
@@ -145,20 +203,25 @@ namespace OpenSim.Region.ClientStack.Linden
145 { 203 {
146 private List<Hashtable> requests = 204 private List<Hashtable> requests =
147 new List<Hashtable>(); 205 new List<Hashtable>();
148 private Dictionary<UUID, Hashtable> responses = 206 private Dictionary<UUID, aPollResponse> responses =
149 new Dictionary<UUID, Hashtable>(); 207 new Dictionary<UUID, aPollResponse>();
150 208
151 private Scene m_scene; 209 private Scene m_scene;
152 210 private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000);
153 public PollServiceTextureEventArgs(UUID pId, Scene scene) : 211 public PollServiceTextureEventArgs(UUID pId, Scene scene) :
154 base(null, null, null, null, pId, int.MaxValue) 212 base(null, null, null, null, pId, int.MaxValue)
155 { 213 {
156 m_scene = scene; 214 m_scene = scene;
157 215 // x is request id, y is userid
158 HasEvents = (x, y) => 216 HasEvents = (x, y) =>
159 { 217 {
160 lock (responses) 218 lock (responses)
161 return responses.ContainsKey(x); 219 {
220 bool ret = m_throttler.hasEvents(x, responses);
221 m_throttler.ProcessTime();
222 return ret;
223
224 }
162 }; 225 };
163 GetEvents = (x, y) => 226 GetEvents = (x, y) =>
164 { 227 {
@@ -166,7 +229,7 @@ namespace OpenSim.Region.ClientStack.Linden
166 { 229 {
167 try 230 try
168 { 231 {
169 return responses[x]; 232 return responses[x].response;
170 } 233 }
171 finally 234 finally
172 { 235 {
@@ -174,14 +237,14 @@ namespace OpenSim.Region.ClientStack.Linden
174 } 237 }
175 } 238 }
176 }; 239 };
177 240 // x is request id, y is request data hashtable
178 Request = (x, y) => 241 Request = (x, y) =>
179 { 242 {
180 aPollRequest reqinfo = new aPollRequest(); 243 aPollRequest reqinfo = new aPollRequest();
181 reqinfo.thepoll = this; 244 reqinfo.thepoll = this;
182 reqinfo.reqID = x; 245 reqinfo.reqID = x;
183 reqinfo.request = y; 246 reqinfo.request = y;
184 247
185 m_queue.Enqueue(reqinfo); 248 m_queue.Enqueue(reqinfo);
186 }; 249 };
187 250
@@ -223,16 +286,29 @@ namespace OpenSim.Region.ClientStack.Linden
223 response["content_type"] = "text/plain"; 286 response["content_type"] = "text/plain";
224 response["keepalive"] = false; 287 response["keepalive"] = false;
225 response["reusecontext"] = false; 288 response["reusecontext"] = false;
226 289
227 lock (responses) 290 lock (responses)
228 responses[requestID] = response; 291 responses[requestID] = new aPollResponse() {bytes = 0, response = response};
229 292
230 return; 293 return;
231 } 294 }
232 295
233 response = m_getTextureHandler.Handle(requestinfo.request); 296 response = m_getTextureHandler.Handle(requestinfo.request);
234 lock (responses) 297 lock (responses)
235 responses[requestID] = response; 298 {
299 responses[requestID] = new aPollResponse()
300 {
301 bytes = (int) response["int_bytes"],
302 response = response
303 };
304
305 }
306 m_throttler.ProcessTime();
307 }
308
309 internal void UpdateThrottle(int pimagethrottle)
310 {
311 m_throttler.ThrottleBytes = pimagethrottle;
236 } 312 }
237 } 313 }
238 314
@@ -257,19 +333,23 @@ namespace OpenSim.Region.ClientStack.Linden
257 protocol = "https"; 333 protocol = "https";
258 } 334 }
259 caps.RegisterHandler("GetTexture", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl)); 335 caps.RegisterHandler("GetTexture", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
260 336 m_pollservices.Add(agentID, args);
261 m_capsDict[agentID] = capUrl; 337 m_capsDict[agentID] = capUrl;
262 } 338 }
263 339
264 private void DeregisterCaps(UUID agentID, Caps caps) 340 private void DeregisterCaps(UUID agentID, Caps caps)
265 { 341 {
266 string capUrl; 342 string capUrl;
267 343 PollServiceTextureEventArgs args;
268 if (m_capsDict.TryGetValue(agentID, out capUrl)) 344 if (m_capsDict.TryGetValue(agentID, out capUrl))
269 { 345 {
270 MainServer.Instance.RemoveHTTPHandler("", capUrl); 346 MainServer.Instance.RemoveHTTPHandler("", capUrl);
271 m_capsDict.Remove(agentID); 347 m_capsDict.Remove(agentID);
272 } 348 }
349 if (m_pollservices.TryGetValue(agentID, out args))
350 {
351 m_pollservices.Remove(agentID);
352 }
273 } 353 }
274 354
275 private void DoTextureRequests() 355 private void DoTextureRequests()
@@ -281,5 +361,81 @@ namespace OpenSim.Region.ClientStack.Linden
281 poolreq.thepoll.Process(poolreq); 361 poolreq.thepoll.Process(poolreq);
282 } 362 }
283 } 363 }
364 internal sealed class CapsDataThrottler
365 {
366
367 private volatile int currenttime = 0;
368 private volatile int lastTimeElapsed = 0;
369 private volatile int BytesSent = 0;
370 private int oversizedImages = 0;
371 public CapsDataThrottler(int pBytes, int max, int min)
372 {
373 ThrottleBytes = pBytes;
374 lastTimeElapsed = Util.EnvironmentTickCount();
375 }
376 public bool hasEvents(UUID key, Dictionary<UUID, GetTextureModule.aPollResponse> responses)
377 {
378 PassTime();
379 // Note, this is called IN LOCK
380 bool haskey = responses.ContainsKey(key);
381 if (!haskey)
382 {
383 return false;
384 }
385 GetTextureModule.aPollResponse response;
386 if (responses.TryGetValue(key, out response))
387 {
388
389 // Normal
390 if (BytesSent + response.bytes <= ThrottleBytes)
391 {
392 BytesSent += response.bytes;
393 //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + 1000, unlockyn = false };
394 //m_actions.Add(timeBasedAction);
395 return true;
396 }
397 // Big textures
398 else if (response.bytes > ThrottleBytes && oversizedImages <= ((ThrottleBytes % 50000) + 1))
399 {
400 Interlocked.Increment(ref oversizedImages);
401 BytesSent += response.bytes;
402 //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + (((response.bytes % ThrottleBytes)+1)*1000) , unlockyn = false };
403 //m_actions.Add(timeBasedAction);
404 return true;
405 }
406 else
407 {
408 return false;
409 }
410 }
411
412 return haskey;
413 }
414 public void ProcessTime()
415 {
416 PassTime();
417 }
418
419
420 private void PassTime()
421 {
422 currenttime = Util.EnvironmentTickCount();
423 int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed);
424 //processTimeBasedActions(responses);
425 if (Util.EnvironmentTickCountSubtract(currenttime, timeElapsed) >= 1000)
426 {
427 lastTimeElapsed = Util.EnvironmentTickCount();
428 BytesSent -= ThrottleBytes;
429 if (BytesSent < 0) BytesSent = 0;
430 if (BytesSent < ThrottleBytes)
431 {
432 oversizedImages = 0;
433 }
434 }
435 }
436 public int ThrottleBytes;
437 }
284 } 438 }
439
440
285} 441}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
index 0251ac4..60c1814 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Region.ClientStack.Linden
45 /// <summary> 45 /// <summary>
46 /// MeshUploadFlag capability. This is required for uploading Mesh. 46 /// MeshUploadFlag capability. This is required for uploading Mesh.
47 /// </summary> 47 /// </summary>
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MeshUploadFlagModule")]
49 public class MeshUploadFlagModule : INonSharedRegionModule 49 public class MeshUploadFlagModule : INonSharedRegionModule
50 { 50 {
51// private static readonly ILog m_log = 51// private static readonly ILog m_log =
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
index 4ccfc43..92805e2 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
@@ -32,6 +32,7 @@ using log4net;
32using Nini.Config; 32using Nini.Config;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.StructuredData; 34using OpenMetaverse.StructuredData;
35using Mono.Addins;
35using OpenSim.Framework; 36using OpenSim.Framework;
36using OpenSim.Framework.Servers; 37using OpenSim.Framework.Servers;
37using OpenSim.Framework.Servers.HttpServer; 38using OpenSim.Framework.Servers.HttpServer;
@@ -41,30 +42,60 @@ using Caps=OpenSim.Framework.Capabilities.Caps;
41 42
42namespace OpenSim.Region.ClientStack.Linden 43namespace OpenSim.Region.ClientStack.Linden
43{ 44{
44 public class ObjectAdd : IRegionModule 45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ObjectAdd")]
46 public class ObjectAdd : INonSharedRegionModule
45 { 47 {
46// private static readonly ILog m_log = 48// private static readonly ILog m_log =
47// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 50
49 private Scene m_scene; 51 private Scene m_scene;
50 #region IRegionModule Members
51 52
52 public void Initialise(Scene pScene, IConfigSource pSource) 53 #region INonSharedRegionModule Members
54
55 public void Initialise(IConfigSource pSource)
56 {
57 }
58
59 public void AddRegion(Scene scene)
53 { 60 {
54 m_scene = pScene; 61 m_scene = scene;
55 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 62 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
56 } 63 }
57 64
58 public void PostInitialise() 65 public void RemoveRegion(Scene scene)
59 { 66 {
60 67 if (m_scene == scene)
68 {
69 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
70 m_scene = null;
71 }
61 } 72 }
62 73
74 public void RegionLoaded(Scene scene)
75 {
76 }
77
78 public void Close()
79 {
80 }
81
82 public string Name
83 {
84 get { return "ObjectAddModule"; }
85 }
86
87 public Type ReplaceableInterface
88 {
89 get { return null; }
90 }
91
92 #endregion
93
63 public void RegisterCaps(UUID agentID, Caps caps) 94 public void RegisterCaps(UUID agentID, Caps caps)
64 { 95 {
65 UUID capuuid = UUID.Random(); 96 UUID capuuid = UUID.Random();
66 97
67// m_log.InfoFormat("[OBJECTADD]: {0}", "/CAPS/OA/" + capuuid + "/"); 98 // m_log.InfoFormat("[OBJECTADD]: {0}", "/CAPS/OA/" + capuuid + "/");
68 99
69 caps.RegisterHandler( 100 caps.RegisterHandler(
70 "ObjectAdd", 101 "ObjectAdd",
@@ -73,7 +104,7 @@ namespace OpenSim.Region.ClientStack.Linden
73 "/CAPS/OA/" + capuuid + "/", 104 "/CAPS/OA/" + capuuid + "/",
74 httpMethod => ProcessAdd(httpMethod, agentID, caps), 105 httpMethod => ProcessAdd(httpMethod, agentID, caps),
75 "ObjectAdd", 106 "ObjectAdd",
76 agentID.ToString()));; 107 agentID.ToString())); ;
77 } 108 }
78 109
79 public Hashtable ProcessAdd(Hashtable request, UUID AgentId, Caps cap) 110 public Hashtable ProcessAdd(Hashtable request, UUID AgentId, Caps cap)
@@ -84,7 +115,7 @@ namespace OpenSim.Region.ClientStack.Linden
84 responsedata["keepalive"] = false; 115 responsedata["keepalive"] = false;
85 responsedata["str_response_string"] = "Request wasn't what was expected"; 116 responsedata["str_response_string"] = "Request wasn't what was expected";
86 ScenePresence avatar; 117 ScenePresence avatar;
87 118
88 if (!m_scene.TryGetScenePresence(AgentId, out avatar)) 119 if (!m_scene.TryGetScenePresence(AgentId, out avatar))
89 return responsedata; 120 return responsedata;
90 121
@@ -127,7 +158,7 @@ namespace OpenSim.Region.ClientStack.Linden
127 158
128 if (r.Type != OSDType.Map) // not a proper req 159 if (r.Type != OSDType.Map) // not a proper req
129 return responsedata; 160 return responsedata;
130 161
131 OSDMap rm = (OSDMap)r; 162 OSDMap rm = (OSDMap)r;
132 163
133 if (rm.ContainsKey("ObjectData")) //v2 164 if (rm.ContainsKey("ObjectData")) //v2
@@ -138,7 +169,7 @@ namespace OpenSim.Region.ClientStack.Linden
138 return responsedata; 169 return responsedata;
139 } 170 }
140 171
141 OSDMap ObjMap = (OSDMap) rm["ObjectData"]; 172 OSDMap ObjMap = (OSDMap)rm["ObjectData"];
142 173
143 bypass_raycast = ObjMap["BypassRaycast"].AsBoolean(); 174 bypass_raycast = ObjMap["BypassRaycast"].AsBoolean();
144 everyone_mask = readuintval(ObjMap["EveryoneMask"]); 175 everyone_mask = readuintval(ObjMap["EveryoneMask"]);
@@ -181,7 +212,7 @@ namespace OpenSim.Region.ClientStack.Linden
181 responsedata["str_response_string"] = "Has Profile key, but data not in expected format"; 212 responsedata["str_response_string"] = "Has Profile key, but data not in expected format";
182 return responsedata; 213 return responsedata;
183 } 214 }
184 215
185 OSDMap ProfileMap = (OSDMap)ObjMap["Profile"]; 216 OSDMap ProfileMap = (OSDMap)ObjMap["Profile"];
186 217
187 profile_begin = ProfileMap["Begin"].AsInteger(); 218 profile_begin = ProfileMap["Begin"].AsInteger();
@@ -190,14 +221,14 @@ namespace OpenSim.Region.ClientStack.Linden
190 hollow = ProfileMap["Hollow"].AsInteger(); 221 hollow = ProfileMap["Hollow"].AsInteger();
191 } 222 }
192 ray_end_is_intersection = ObjMap["RayEndIsIntersection"].AsBoolean(); 223 ray_end_is_intersection = ObjMap["RayEndIsIntersection"].AsBoolean();
193 224
194 ray_target_id = ObjMap["RayTargetId"].AsUUID(); 225 ray_target_id = ObjMap["RayTargetId"].AsUUID();
195 state = ObjMap["State"].AsInteger(); 226 state = ObjMap["State"].AsInteger();
196 try 227 try
197 { 228 {
198 ray_end = ((OSDArray) ObjMap["RayEnd"]).AsVector3(); 229 ray_end = ((OSDArray)ObjMap["RayEnd"]).AsVector3();
199 ray_start = ((OSDArray) ObjMap["RayStart"]).AsVector3(); 230 ray_start = ((OSDArray)ObjMap["RayStart"]).AsVector3();
200 scale = ((OSDArray) ObjMap["Scale"]).AsVector3(); 231 scale = ((OSDArray)ObjMap["Scale"]).AsVector3();
201 rotation = ((OSDArray)ObjMap["Rotation"]).AsQuaternion(); 232 rotation = ((OSDArray)ObjMap["Rotation"]).AsQuaternion();
202 } 233 }
203 catch (Exception) 234 catch (Exception)
@@ -214,7 +245,7 @@ namespace OpenSim.Region.ClientStack.Linden
214 return responsedata; 245 return responsedata;
215 } 246 }
216 247
217 OSDMap AgentDataMap = (OSDMap) rm["AgentData"]; 248 OSDMap AgentDataMap = (OSDMap)rm["AgentData"];
218 249
219 //session_id = AgentDataMap["SessionId"].AsUUID(); 250 //session_id = AgentDataMap["SessionId"].AsUUID();
220 group_id = AgentDataMap["GroupId"].AsUUID(); 251 group_id = AgentDataMap["GroupId"].AsUUID();
@@ -251,21 +282,21 @@ namespace OpenSim.Region.ClientStack.Linden
251 profile_begin = rm["profile_begin"].AsInteger(); 282 profile_begin = rm["profile_begin"].AsInteger();
252 profile_curve = rm["profile_curve"].AsInteger(); 283 profile_curve = rm["profile_curve"].AsInteger();
253 profile_end = rm["profile_end"].AsInteger(); 284 profile_end = rm["profile_end"].AsInteger();
254 285
255 ray_end_is_intersection = rm["ray_end_is_intersection"].AsBoolean(); 286 ray_end_is_intersection = rm["ray_end_is_intersection"].AsBoolean();
256 287
257 ray_target_id = rm["ray_target_id"].AsUUID(); 288 ray_target_id = rm["ray_target_id"].AsUUID();
258 289
259 290
260 //session_id = rm["session_id"].AsUUID(); 291 //session_id = rm["session_id"].AsUUID();
261 state = rm["state"].AsInteger(); 292 state = rm["state"].AsInteger();
262 try 293 try
263 { 294 {
264 ray_end = ((OSDArray)rm["ray_end"]).AsVector3(); 295 ray_end = ((OSDArray)rm["ray_end"]).AsVector3();
265 ray_start = ((OSDArray)rm["ray_start"]).AsVector3(); 296 ray_start = ((OSDArray)rm["ray_start"]).AsVector3();
266 rotation = ((OSDArray)rm["rotation"]).AsQuaternion(); 297 rotation = ((OSDArray)rm["rotation"]).AsQuaternion();
267 scale = ((OSDArray)rm["scale"]).AsVector3(); 298 scale = ((OSDArray)rm["scale"]).AsVector3();
268 } 299 }
269 catch (Exception) 300 catch (Exception)
270 { 301 {
271 responsedata["str_response_string"] = "RayEnd, RayStart, Scale or Rotation wasn't in the expected format"; 302 responsedata["str_response_string"] = "RayEnd, RayStart, Scale or Rotation wasn't in the expected format";
@@ -273,9 +304,9 @@ namespace OpenSim.Region.ClientStack.Linden
273 } 304 }
274 } 305 }
275 306
276
277 307
278 Vector3 pos = m_scene.GetNewRezLocation(ray_start, ray_end, ray_target_id, rotation, (bypass_raycast) ? (byte)1 : (byte)0, (ray_end_is_intersection) ? (byte)1 : (byte)0, true, scale, false); 308
309 Vector3 pos = m_scene.GetNewRezLocation(ray_start, ray_end, ray_target_id, rotation, (bypass_raycast) ? (byte)1 : (byte)0, (ray_end_is_intersection) ? (byte)1 : (byte)0, true, scale, false);
279 310
280 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox(); 311 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
281 312
@@ -286,17 +317,17 @@ namespace OpenSim.Region.ClientStack.Linden
286 pbs.PathRevolutions = (byte)path_revolutions; 317 pbs.PathRevolutions = (byte)path_revolutions;
287 pbs.PathScaleX = (byte)path_scale_x; 318 pbs.PathScaleX = (byte)path_scale_x;
288 pbs.PathScaleY = (byte)path_scale_y; 319 pbs.PathScaleY = (byte)path_scale_y;
289 pbs.PathShearX = (byte) path_shear_x; 320 pbs.PathShearX = (byte)path_shear_x;
290 pbs.PathShearY = (byte)path_shear_y; 321 pbs.PathShearY = (byte)path_shear_y;
291 pbs.PathSkew = (sbyte)path_skew; 322 pbs.PathSkew = (sbyte)path_skew;
292 pbs.PathTaperX = (sbyte)path_taper_x; 323 pbs.PathTaperX = (sbyte)path_taper_x;
293 pbs.PathTaperY = (sbyte)path_taper_y; 324 pbs.PathTaperY = (sbyte)path_taper_y;
294 pbs.PathTwist = (sbyte)path_twist; 325 pbs.PathTwist = (sbyte)path_twist;
295 pbs.PathTwistBegin = (sbyte)path_twist_begin; 326 pbs.PathTwistBegin = (sbyte)path_twist_begin;
296 pbs.HollowShape = (HollowShape) hollow; 327 pbs.HollowShape = (HollowShape)hollow;
297 pbs.PCode = (byte)p_code; 328 pbs.PCode = (byte)p_code;
298 pbs.ProfileBegin = (ushort) profile_begin; 329 pbs.ProfileBegin = (ushort)profile_begin;
299 pbs.ProfileCurve = (byte) profile_curve; 330 pbs.ProfileCurve = (byte)profile_curve;
300 pbs.ProfileEnd = (ushort)profile_end; 331 pbs.ProfileEnd = (ushort)profile_end;
301 pbs.Scale = scale; 332 pbs.Scale = scale;
302 pbs.State = (byte)state; 333 pbs.State = (byte)state;
@@ -306,7 +337,7 @@ namespace OpenSim.Region.ClientStack.Linden
306 if (m_scene.Permissions.CanRezObject(1, avatar.UUID, pos)) 337 if (m_scene.Permissions.CanRezObject(1, avatar.UUID, pos))
307 { 338 {
308 // rez ON the ground, not IN the ground 339 // rez ON the ground, not IN the ground
309 // pos.Z += 0.25F; 340 // pos.Z += 0.25F;
310 341
311 obj = m_scene.AddNewPrim(avatar.UUID, group_id, pos, rotation, pbs); 342 obj = m_scene.AddNewPrim(avatar.UUID, group_id, pos, rotation, pbs);
312 } 343 }
@@ -323,13 +354,13 @@ namespace OpenSim.Region.ClientStack.Linden
323 rootpart.GroupMask = group_mask; 354 rootpart.GroupMask = group_mask;
324 rootpart.NextOwnerMask = next_owner_mask; 355 rootpart.NextOwnerMask = next_owner_mask;
325 rootpart.Material = (byte)material; 356 rootpart.Material = (byte)material;
326 357
327 m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor); 358 m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor);
328 359
329 responsedata["int_response_code"] = 200; //501; //410; //404; 360 responsedata["int_response_code"] = 200; //501; //410; //404;
330 responsedata["content_type"] = "text/plain"; 361 responsedata["content_type"] = "text/plain";
331 responsedata["keepalive"] = false; 362 responsedata["keepalive"] = false;
332 responsedata["str_response_string"] = String.Format("<llsd><map><key>local_id</key>{0}</map></llsd>",ConvertUintToBytes(obj.LocalId)); 363 responsedata["str_response_string"] = String.Format("<llsd><map><key>local_id</key>{0}</map></llsd>", ConvertUintToBytes(obj.LocalId));
333 364
334 return responsedata; 365 return responsedata;
335 } 366 }
@@ -347,24 +378,8 @@ namespace OpenSim.Region.ClientStack.Linden
347 byte[] resultbytes = Utils.UIntToBytes(val); 378 byte[] resultbytes = Utils.UIntToBytes(val);
348 if (BitConverter.IsLittleEndian) 379 if (BitConverter.IsLittleEndian)
349 Array.Reverse(resultbytes); 380 Array.Reverse(resultbytes);
350 return String.Format("<binary encoding=\"base64\">{0}</binary>",Convert.ToBase64String(resultbytes)); 381 return String.Format("<binary encoding=\"base64\">{0}</binary>", Convert.ToBase64String(resultbytes));
351 }
352
353 public void Close()
354 {
355
356 }
357
358 public string Name
359 {
360 get { return "ObjectAddModule"; }
361 }
362
363 public bool IsSharedModule
364 {
365 get { return false; }
366 } 382 }
367 383
368 #endregion
369 } 384 }
370} 385}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
index ba902b2..55a503e 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
@@ -51,14 +51,14 @@ using ExtraParamType = OpenMetaverse.ExtraParamType;
51 51
52namespace OpenSim.Region.ClientStack.Linden 52namespace OpenSim.Region.ClientStack.Linden
53{ 53{
54 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 54 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UploadObjectAssetModule")]
55 public class UploadObjectAssetModule : INonSharedRegionModule 55 public class UploadObjectAssetModule : INonSharedRegionModule
56 { 56 {
57 private static readonly ILog m_log = 57 private static readonly ILog m_log =
58 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 58 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59 private Scene m_scene; 59 private Scene m_scene;
60 60
61 #region IRegionModuleBase Members 61 #region Region Module interfaceBase Members
62 62
63 63
64 public Type ReplaceableInterface 64 public Type ReplaceableInterface
@@ -92,7 +92,7 @@ namespace OpenSim.Region.ClientStack.Linden
92 #endregion 92 #endregion
93 93
94 94
95 #region IRegionModule Members 95 #region Region Module interface
96 96
97 97
98 98
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..060a61c
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.ClientStack.LindenCaps")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("1ae76353-f37f-4fe3-b6df-d11cedf01f2c")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
index 0a5ad0f..fcac182 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
@@ -109,7 +109,7 @@ namespace OpenSim.Region.ClientStack.Linden
109 109
110 UUID capID = UUID.Random(); 110 UUID capID = UUID.Random();
111 111
112 m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); 112// m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName);
113 caps.RegisterHandler( 113 caps.RegisterHandler(
114 "SimConsoleAsync", 114 "SimConsoleAsync",
115 new ConsoleHandler("/CAPS/" + capID + "/", "SimConsoleAsync", agentID, this, m_scene)); 115 new ConsoleHandler("/CAPS/" + capID + "/", "SimConsoleAsync", agentID, this, m_scene));
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
index 8ed0fb3..191bccf 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
@@ -53,7 +53,7 @@ namespace OpenSim.Region.ClientStack.Linden
53 /// NOTE: Part of this code was adapted from the Aurora project, specifically 53 /// NOTE: Part of this code was adapted from the Aurora project, specifically
54 /// the normal part of the response in the capability handler. 54 /// the normal part of the response in the capability handler.
55 /// </remarks> 55 /// </remarks>
56 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 56 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimulatorFeaturesModule")]
57 public class SimulatorFeaturesModule : ISharedRegionModule, ISimulatorFeaturesModule 57 public class SimulatorFeaturesModule : ISharedRegionModule, ISimulatorFeaturesModule
58 { 58 {
59// private static readonly ILog m_log = 59// private static readonly ILog m_log =
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
index 6aac591..3b0ccd7 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
@@ -50,7 +50,7 @@ using OpenSim.Capabilities.Handlers;
50 50
51namespace OpenSim.Region.ClientStack.Linden 51namespace OpenSim.Region.ClientStack.Linden
52{ 52{
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UploadBakedTextureModule")]
54 public class UploadBakedTextureModule : INonSharedRegionModule 54 public class UploadBakedTextureModule : INonSharedRegionModule
55 { 55 {
56// private static readonly ILog m_log = 56// private static readonly ILog m_log =
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 0caeddf..04cd474 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.ClientStack.Linden
49 /// <summary> 49 /// <summary>
50 /// This module implements both WebFetchInventoryDescendents and FetchInventoryDescendents2 capabilities. 50 /// This module implements both WebFetchInventoryDescendents and FetchInventoryDescendents2 capabilities.
51 /// </summary> 51 /// </summary>
52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WebFetchInvDescModule")]
53 public class WebFetchInvDescModule : INonSharedRegionModule 53 public class WebFetchInvDescModule : INonSharedRegionModule
54 { 54 {
55 struct aPollRequest 55 struct aPollRequest
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
index 1b8535c..e22670b 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
@@ -45,7 +45,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
45 public Packet Packet; 45 public Packet Packet;
46 46
47 /// <summary> 47 /// <summary>
48 /// Default constructor 48 /// No arg constructor.
49 /// </summary>
50 public IncomingPacket() {}
51
52 /// <summary>
53 /// Constructor
49 /// </summary> 54 /// </summary>
50 /// <param name="client">Reference to the client this packet came from</param> 55 /// <param name="client">Reference to the client this packet came from</param>
51 /// <param name="packet">Packet data</param> 56 /// <param name="packet">Packet data</param>
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index ee28914..8e0b72f 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -47,6 +47,7 @@ using OpenSim.Region.Framework.Scenes;
47using OpenSim.Services.Interfaces; 47using OpenSim.Services.Interfaces;
48using Timer = System.Timers.Timer; 48using Timer = System.Timers.Timer;
49using AssetLandmark = OpenSim.Framework.AssetLandmark; 49using AssetLandmark = OpenSim.Framework.AssetLandmark;
50using RegionFlags = OpenMetaverse.RegionFlags;
50using Nini.Config; 51using Nini.Config;
51 52
52using System.IO; 53using System.IO;
@@ -295,6 +296,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
295 public event MuteListEntryRemove OnRemoveMuteListEntry; 296 public event MuteListEntryRemove OnRemoveMuteListEntry;
296 public event GodlikeMessage onGodlikeMessage; 297 public event GodlikeMessage onGodlikeMessage;
297 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 298 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
299 public event GenericCall2 OnUpdateThrottles;
298 300
299 #endregion Events 301 #endregion Events
300 302
@@ -354,7 +356,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
354 private bool m_deliverPackets = true; 356 private bool m_deliverPackets = true;
355 private int m_animationSequenceNumber = 1; 357 private int m_animationSequenceNumber = 1;
356 private bool m_SendLogoutPacketWhenClosing = true; 358 private bool m_SendLogoutPacketWhenClosing = true;
357 private AgentUpdateArgs lastarg; 359
360 /// <summary>
361 /// We retain a single AgentUpdateArgs so that we can constantly reuse it rather than construct a new one for
362 /// every single incoming AgentUpdate. Every client sends 10 AgentUpdate UDP messages per second, even if it
363 /// is doing absolutely nothing.
364 /// </summary>
365 /// <remarks>
366 /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods
367 /// cannot retain a reference to it outside of that method.
368 /// </remarks>
369 private AgentUpdateArgs m_lastAgentUpdateArgs;
358 370
359 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); 371 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
360 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 372 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@@ -509,19 +521,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
509 /// </summary> 521 /// </summary>
510 public void Close() 522 public void Close()
511 { 523 {
512 Close(true); 524 Close(true, false);
513 } 525 }
514 526
515 /// <summary> 527 public void Close(bool sendStop, bool force)
516 /// Shut down the client view
517 /// </summary>
518 public void Close(bool sendStop)
519 { 528 {
520 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. 529 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
521 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. 530 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
522 lock (CloseSyncLock) 531 lock (CloseSyncLock)
523 { 532 {
524 if (!IsActive) 533 // We still perform a force close inside the sync lock since this is intended to attempt close where
534 // there is some unidentified connection problem, not where we have issues due to deadlock
535 if (!IsActive && !force)
525 return; 536 return;
526 537
527 IsActive = false; 538 IsActive = false;
@@ -836,8 +847,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
836 OutPacket(mov, ThrottleOutPacketType.Unknown); 847 OutPacket(mov, ThrottleOutPacketType.Unknown);
837 } 848 }
838 849
839 public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, 850 public void SendChatMessage(
840 UUID fromAgentID, byte source, byte audible) 851 string message, byte type, Vector3 fromPos, string fromName,
852 UUID fromAgentID, UUID ownerID, byte source, byte audible)
841 { 853 {
842 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); 854 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator);
843 reply.ChatData.Audible = audible; 855 reply.ChatData.Audible = audible;
@@ -846,7 +858,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
846 reply.ChatData.SourceType = source; 858 reply.ChatData.SourceType = source;
847 reply.ChatData.Position = fromPos; 859 reply.ChatData.Position = fromPos;
848 reply.ChatData.FromName = Util.StringToBytes256(fromName); 860 reply.ChatData.FromName = Util.StringToBytes256(fromName);
849 reply.ChatData.OwnerID = fromAgentID; 861 reply.ChatData.OwnerID = ownerID;
850 reply.ChatData.SourceID = fromAgentID; 862 reply.ChatData.SourceID = fromAgentID;
851 863
852 OutPacket(reply, ThrottleOutPacketType.Unknown); 864 OutPacket(reply, ThrottleOutPacketType.Unknown);
@@ -3984,7 +3996,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3984 { 3996 {
3985 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 3997 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3986 3998
3987 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3999 ImprovedTerseObjectUpdatePacket packet
4000 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3988 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4001 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3989 packet.RegionData.TimeDilation = timeDilation; 4002 packet.RegionData.TimeDilation = timeDilation;
3990 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 4003 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
@@ -4029,7 +4042,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4029 { 4042 {
4030 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; 4043 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
4031 4044
4032 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 4045 ImprovedTerseObjectUpdatePacket packet
4046 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
4047 PacketType.ImprovedTerseObjectUpdate);
4033 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4048 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4034 packet.RegionData.TimeDilation = timeDilation; 4049 packet.RegionData.TimeDilation = timeDilation;
4035 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 4050 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
@@ -4037,7 +4052,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4037 for (int i = 0; i < blocks.Count; i++) 4052 for (int i = 0; i < blocks.Count; i++)
4038 packet.ObjectData[i] = blocks[i]; 4053 packet.ObjectData[i] = blocks[i];
4039 4054
4040 OutPacket(packet, ThrottleOutPacketType.Task, true); 4055 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
4041 } 4056 }
4042 4057
4043 #endregion Packet Sending 4058 #endregion Packet Sending
@@ -4534,7 +4549,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4534 { 4549 {
4535 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock(); 4550 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock();
4536 } 4551 }
4537 j = 0; 4552 j = 0;
4538 4553
4539 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; 4554 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
4540 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; 4555 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++;
@@ -5038,7 +5053,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5038 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; 5053 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2;
5039 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; 5054 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2;
5040 5055
5041 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); 5056 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block
5057 = PacketPool.Instance.GetDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
5058
5042 block.Data = data; 5059 block.Data = data;
5043 5060
5044 if (textureEntry != null && textureEntry.Length > 0) 5061 if (textureEntry != null && textureEntry.Length > 0)
@@ -5288,14 +5305,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5288 protected virtual void RegisterLocalPacketHandlers() 5305 protected virtual void RegisterLocalPacketHandlers()
5289 { 5306 {
5290 AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout); 5307 AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout);
5308
5309 // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs
5310 // for each AgentUpdate packet.
5291 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); 5311 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false);
5312
5292 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); 5313 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false);
5293 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); 5314 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false);
5294 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); 5315 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false);
5295 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); 5316 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false);
5296 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); 5317 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false);
5297 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest, false); 5318 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest);
5298 AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest, false); 5319 AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest);
5299 AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); 5320 AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage);
5300 AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest); 5321 AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest);
5301 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); 5322 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer);
@@ -5395,9 +5416,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5395 AddLocalPacketHandler(PacketType.RemoveTaskInventory, HandleRemoveTaskInventory); 5416 AddLocalPacketHandler(PacketType.RemoveTaskInventory, HandleRemoveTaskInventory);
5396 AddLocalPacketHandler(PacketType.MoveTaskInventory, HandleMoveTaskInventory); 5417 AddLocalPacketHandler(PacketType.MoveTaskInventory, HandleMoveTaskInventory);
5397 AddLocalPacketHandler(PacketType.RezScript, HandleRezScript); 5418 AddLocalPacketHandler(PacketType.RezScript, HandleRezScript);
5398 AddLocalPacketHandler(PacketType.MapLayerRequest, HandleMapLayerRequest, false); 5419 AddLocalPacketHandler(PacketType.MapLayerRequest, HandleMapLayerRequest);
5399 AddLocalPacketHandler(PacketType.MapBlockRequest, HandleMapBlockRequest, false); 5420 AddLocalPacketHandler(PacketType.MapBlockRequest, HandleMapBlockRequest);
5400 AddLocalPacketHandler(PacketType.MapNameRequest, HandleMapNameRequest, false); 5421 AddLocalPacketHandler(PacketType.MapNameRequest, HandleMapNameRequest);
5401 AddLocalPacketHandler(PacketType.TeleportLandmarkRequest, HandleTeleportLandmarkRequest); 5422 AddLocalPacketHandler(PacketType.TeleportLandmarkRequest, HandleTeleportLandmarkRequest);
5402 AddLocalPacketHandler(PacketType.TeleportCancel, HandleTeleportCancel); 5423 AddLocalPacketHandler(PacketType.TeleportCancel, HandleTeleportCancel);
5403 AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest); 5424 AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest);
@@ -5517,81 +5538,84 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5517 5538
5518 #region Scene/Avatar 5539 #region Scene/Avatar
5519 5540
5520 private bool HandleAgentUpdate(IClientAPI sener, Packet Pack) 5541 private bool HandleAgentUpdate(IClientAPI sener, Packet packet)
5521 { 5542 {
5522 if (OnAgentUpdate != null) 5543 if (OnAgentUpdate != null)
5523 { 5544 {
5524 bool update = false; 5545 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
5525 AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack;
5526 5546
5527 #region Packet Session and User Check 5547 #region Packet Session and User Check
5528 if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId) 5548 if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId)
5549 {
5550 PacketPool.Instance.ReturnPacket(packet);
5529 return false; 5551 return false;
5552 }
5530 #endregion 5553 #endregion
5531 5554
5532 AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; 5555 bool update = false;
5533 5556 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData;
5534 // We can only check when we have something to check
5535 // against.
5536 5557
5537 if (lastarg != null) 5558 if (m_lastAgentUpdateArgs != null)
5538 { 5559 {
5560 // These should be ordered from most-likely to
5561 // least likely to change. I've made an initial
5562 // guess at that.
5539 update = 5563 update =
5540 ( 5564 (
5541 (x.BodyRotation != lastarg.BodyRotation) || 5565 (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) ||
5542 (x.CameraAtAxis != lastarg.CameraAtAxis) || 5566 (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) ||
5543 (x.CameraCenter != lastarg.CameraCenter) || 5567 (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) ||
5544 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 5568 (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) ||
5545 (x.CameraUpAxis != lastarg.CameraUpAxis) || 5569 (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) ||
5546 (x.ControlFlags != lastarg.ControlFlags) || 5570 (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) ||
5547 (x.ControlFlags != 0) || 5571 (x.ControlFlags != 0) ||
5548 (x.Far != lastarg.Far) || 5572 (x.Far != m_lastAgentUpdateArgs.Far) ||
5549 (x.Flags != lastarg.Flags) || 5573 (x.Flags != m_lastAgentUpdateArgs.Flags) ||
5550 (x.State != lastarg.State) || 5574 (x.State != m_lastAgentUpdateArgs.State) ||
5551 (x.HeadRotation != lastarg.HeadRotation) || 5575 (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) ||
5552 (x.SessionID != lastarg.SessionID) || 5576 (x.SessionID != m_lastAgentUpdateArgs.SessionID) ||
5553 (x.AgentID != lastarg.AgentID) 5577 (x.AgentID != m_lastAgentUpdateArgs.AgentID)
5554 ); 5578 );
5555 } 5579 }
5556 else 5580 else
5557 { 5581 {
5582 m_lastAgentUpdateArgs = new AgentUpdateArgs();
5558 update = true; 5583 update = true;
5559 } 5584 }
5560 5585
5561 // These should be ordered from most-likely to
5562 // least likely to change. I've made an initial
5563 // guess at that.
5564
5565 if (update) 5586 if (update)
5566 { 5587 {
5567// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); 5588// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name);
5568 5589
5569 AgentUpdateArgs arg = new AgentUpdateArgs(); 5590 m_lastAgentUpdateArgs.AgentID = x.AgentID;
5570 arg.AgentID = x.AgentID; 5591 m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation;
5571 arg.BodyRotation = x.BodyRotation; 5592 m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis;
5572 arg.CameraAtAxis = x.CameraAtAxis; 5593 m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter;
5573 arg.CameraCenter = x.CameraCenter; 5594 m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis;
5574 arg.CameraLeftAxis = x.CameraLeftAxis; 5595 m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis;
5575 arg.CameraUpAxis = x.CameraUpAxis; 5596 m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags;
5576 arg.ControlFlags = x.ControlFlags; 5597 m_lastAgentUpdateArgs.Far = x.Far;
5577 arg.Far = x.Far; 5598 m_lastAgentUpdateArgs.Flags = x.Flags;
5578 arg.Flags = x.Flags; 5599 m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation;
5579 arg.HeadRotation = x.HeadRotation; 5600 m_lastAgentUpdateArgs.SessionID = x.SessionID;
5580 arg.SessionID = x.SessionID; 5601 m_lastAgentUpdateArgs.State = x.State;
5581 arg.State = x.State; 5602
5582 UpdateAgent handlerAgentUpdate = OnAgentUpdate; 5603 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5583 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; 5604 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
5584 lastarg = arg; // save this set of arguments for nexttime 5605
5585 if (handlerPreAgentUpdate != null) 5606 if (handlerPreAgentUpdate != null)
5586 OnPreAgentUpdate(this, arg); 5607 OnPreAgentUpdate(this, m_lastAgentUpdateArgs);
5608
5587 if (handlerAgentUpdate != null) 5609 if (handlerAgentUpdate != null)
5588 OnAgentUpdate(this, arg); 5610 OnAgentUpdate(this, m_lastAgentUpdateArgs);
5589 5611
5590 handlerAgentUpdate = null; 5612 handlerAgentUpdate = null;
5591 handlerPreAgentUpdate = null; 5613 handlerPreAgentUpdate = null;
5592 } 5614 }
5593 } 5615 }
5594 5616
5617 PacketPool.Instance.ReturnPacket(packet);
5618
5595 return true; 5619 return true;
5596 } 5620 }
5597 5621
@@ -5963,7 +5987,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5963 msgpack.MessageBlock.ID, 5987 msgpack.MessageBlock.ID,
5964 msgpack.MessageBlock.Offline != 0 ? true : false, 5988 msgpack.MessageBlock.Offline != 0 ? true : false,
5965 msgpack.MessageBlock.Position, 5989 msgpack.MessageBlock.Position,
5966 msgpack.MessageBlock.BinaryBucket); 5990 msgpack.MessageBlock.BinaryBucket,
5991 true);
5967 5992
5968 handlerInstantMessage(this, im); 5993 handlerInstantMessage(this, im);
5969 } 5994 }
@@ -6729,6 +6754,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6729 #endregion 6754 #endregion
6730 6755
6731 m_udpClient.SetThrottles(atpack.Throttle.Throttles); 6756 m_udpClient.SetThrottles(atpack.Throttle.Throttles);
6757 GenericCall2 handler = OnUpdateThrottles;
6758 if (handler != null)
6759 {
6760 handler();
6761 }
6732 return true; 6762 return true;
6733 } 6763 }
6734 6764
@@ -9245,7 +9275,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9245 } 9275 }
9246 #endregion 9276 #endregion
9247 9277
9248 switch (Utils.BytesToString(messagePacket.MethodData.Method)) 9278 string method = Utils.BytesToString(messagePacket.MethodData.Method);
9279
9280 switch (method)
9249 { 9281 {
9250 case "getinfo": 9282 case "getinfo":
9251 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) 9283 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
@@ -9561,7 +9593,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9561 return true; 9593 return true;
9562 9594
9563 default: 9595 default:
9564 m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); 9596 m_log.WarnFormat(
9597 "[LLCLIENTVIEW]: EstateOwnerMessage: Unknown method {0} requested for {1} in {2}",
9598 method, Name, Scene.Name);
9599
9600 for (int i = 0; i < messagePacket.ParamList.Length; i++)
9601 {
9602 EstateOwnerMessagePacket.ParamListBlock block = messagePacket.ParamList[i];
9603 string data = (string)Utils.BytesToString(block.Parameter);
9604 m_log.DebugFormat("[LLCLIENTVIEW]: Param {0}={1}", i, data);
9605 }
9606
9565 return true; 9607 return true;
9566 } 9608 }
9567 9609
@@ -11870,8 +11912,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11870 public void SetChildAgentThrottle(byte[] throttles) 11912 public void SetChildAgentThrottle(byte[] throttles)
11871 { 11913 {
11872 m_udpClient.SetThrottles(throttles); 11914 m_udpClient.SetThrottles(throttles);
11915 GenericCall2 handler = OnUpdateThrottles;
11916 if (handler != null)
11917 {
11918 handler();
11919 }
11920 }
11921
11922 /// <summary>
11923 /// Sets the throttles from values supplied by the client
11924 /// </summary>
11925 /// <param name="throttles"></param>
11926 public void SetAgentThrottleSilent(int throttle, int setting)
11927 {
11928 m_udpClient.ForceThrottleSetting(throttle,setting);
11929 //m_udpClient.SetThrottles(throttles);
11930
11873 } 11931 }
11874 11932
11933
11875 /// <summary> 11934 /// <summary>
11876 /// Get the current throttles for this client as a packed byte array 11935 /// Get the current throttles for this client as a packed byte array
11877 /// </summary> 11936 /// </summary>
@@ -11949,7 +12008,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11949 logPacket = false; 12008 logPacket = false;
11950 12009
11951 if (DebugPacketLevel <= 50 12010 if (DebugPacketLevel <= 50
11952 & (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) 12011 && (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate))
11953 logPacket = false; 12012 logPacket = false;
11954 12013
11955 if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) 12014 if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily)
@@ -12023,8 +12082,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12023 12082
12024 if (!ProcessPacketMethod(packet)) 12083 if (!ProcessPacketMethod(packet))
12025 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); 12084 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
12026
12027 PacketPool.Instance.ReturnPacket(packet);
12028 } 12085 }
12029 12086
12030 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) 12087 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
@@ -12193,7 +12250,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12193 { 12250 {
12194 Kick(reason); 12251 Kick(reason);
12195 Thread.Sleep(1000); 12252 Thread.Sleep(1000);
12196 Close(); 12253 Disconnect();
12197 } 12254 }
12198 12255
12199 public void Disconnect() 12256 public void Disconnect()
@@ -12481,7 +12538,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12481 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); 12538 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
12482 12539
12483 12540
12484 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 12541 ImprovedTerseObjectUpdatePacket packet
12542 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
12543 PacketType.ImprovedTerseObjectUpdate);
12544
12485 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 12545 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
12486 packet.RegionData.TimeDilation = timeDilation; 12546 packet.RegionData.TimeDilation = timeDilation;
12487 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; 12547 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index c472176..f675377 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -682,6 +682,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
682 if (m_nextOnQueueEmpty == 0) 682 if (m_nextOnQueueEmpty == 0)
683 m_nextOnQueueEmpty = 1; 683 m_nextOnQueueEmpty = 1;
684 } 684 }
685 internal void ForceThrottleSetting(int throttle, int setting)
686 {
687 m_throttleCategories[throttle].RequestedDripRate = Math.Max(setting, LLUDPServer.MTU); ;
688 }
685 689
686 /// <summary> 690 /// <summary>
687 /// Converts a <seealso cref="ThrottleOutPacketType"/> integer to a 691 /// Converts a <seealso cref="ThrottleOutPacketType"/> integer to a
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index dac3306..fc4e1b2 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -37,6 +37,7 @@ using log4net;
37using Nini.Config; 37using Nini.Config;
38using OpenMetaverse.Packets; 38using OpenMetaverse.Packets;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Framework.Console;
40using OpenSim.Framework.Monitoring; 41using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
42using OpenMetaverse; 43using OpenMetaverse;
@@ -69,6 +70,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
69 public void AddScene(IScene scene) 70 public void AddScene(IScene scene)
70 { 71 {
71 m_udpServer.AddScene(scene); 72 m_udpServer.AddScene(scene);
73
74 StatsManager.RegisterStat(
75 new Stat(
76 "IncomingPacketsProcessedCount",
77 "Number of inbound UDP packets processed",
78 "Number of inbound UDP packets processed",
79 "",
80 "clientstack",
81 scene.Name,
82 StatType.Pull,
83 MeasuresOfInterest.AverageChangeOverTime,
84 stat => stat.Value = m_udpServer.IncomingPacketsProcessed,
85 StatVerbosity.Debug));
72 } 86 }
73 87
74 public bool HandlesRegion(Location x) 88 public bool HandlesRegion(Location x)
@@ -100,9 +114,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
100 114
101 /// <summary>The measured resolution of Environment.TickCount</summary> 115 /// <summary>The measured resolution of Environment.TickCount</summary>
102 public readonly float TickCountResolution; 116 public readonly float TickCountResolution;
117
103 /// <summary>Number of prim updates to put on the queue each time the 118 /// <summary>Number of prim updates to put on the queue each time the
104 /// OnQueueEmpty event is triggered for updates</summary> 119 /// OnQueueEmpty event is triggered for updates</summary>
105 public readonly int PrimUpdatesPerCallback; 120 public readonly int PrimUpdatesPerCallback;
121
106 /// <summary>Number of texture packets to put on the queue each time the 122 /// <summary>Number of texture packets to put on the queue each time the
107 /// OnQueueEmpty event is triggered for textures</summary> 123 /// OnQueueEmpty event is triggered for textures</summary>
108 public readonly int TextureSendLimit; 124 public readonly int TextureSendLimit;
@@ -124,28 +140,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
124 140
125 /// <summary>Manages authentication for agent circuits</summary> 141 /// <summary>Manages authentication for agent circuits</summary>
126 private AgentCircuitManager m_circuitManager; 142 private AgentCircuitManager m_circuitManager;
143
127 /// <summary>Reference to the scene this UDP server is attached to</summary> 144 /// <summary>Reference to the scene this UDP server is attached to</summary>
128 protected Scene m_scene; 145 protected Scene m_scene;
146
129 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> 147 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
130 private Location m_location; 148 private Location m_location;
149
131 /// <summary>The size of the receive buffer for the UDP socket. This value 150 /// <summary>The size of the receive buffer for the UDP socket. This value
132 /// is passed up to the operating system and used in the system networking 151 /// is passed up to the operating system and used in the system networking
133 /// stack. Use zero to leave this value as the default</summary> 152 /// stack. Use zero to leave this value as the default</summary>
134 private int m_recvBufferSize; 153 private int m_recvBufferSize;
154
135 /// <summary>Flag to process packets asynchronously or synchronously</summary> 155 /// <summary>Flag to process packets asynchronously or synchronously</summary>
136 private bool m_asyncPacketHandling; 156 private bool m_asyncPacketHandling;
157
137 /// <summary>Tracks whether or not a packet was sent each round so we know 158 /// <summary>Tracks whether or not a packet was sent each round so we know
138 /// whether or not to sleep</summary> 159 /// whether or not to sleep</summary>
139 private bool m_packetSent; 160 private bool m_packetSent;
140 161
141 /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary> 162 /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary>
142 private int m_elapsedMSSinceLastStatReport = 0; 163 private int m_elapsedMSSinceLastStatReport = 0;
164
143 /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary> 165 /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary>
144 private int m_tickLastOutgoingPacketHandler; 166 private int m_tickLastOutgoingPacketHandler;
167
145 /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary> 168 /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary>
146 private int m_elapsedMSOutgoingPacketHandler; 169 private int m_elapsedMSOutgoingPacketHandler;
170
147 /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary> 171 /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary>
148 private int m_elapsed100MSOutgoingPacketHandler; 172 private int m_elapsed100MSOutgoingPacketHandler;
173
149 /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary> 174 /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary>
150 private int m_elapsed500MSOutgoingPacketHandler; 175 private int m_elapsed500MSOutgoingPacketHandler;
151 176
@@ -159,6 +184,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
159 protected bool m_sendPing; 184 protected bool m_sendPing;
160 185
161 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); 186 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
187 private Pool<IncomingPacket> m_incomingPacketPool;
188
189 /// <summary>
190 /// Stat for number of packets in the main pool awaiting use.
191 /// </summary>
192 private Stat m_poolCountStat;
193
194 /// <summary>
195 /// Stat for number of packets in the inbound packet pool awaiting use.
196 /// </summary>
197 private Stat m_incomingPacketPoolStat;
162 198
163 private int m_defaultRTO = 0; 199 private int m_defaultRTO = 0;
164 private int m_maxRTO = 0; 200 private int m_maxRTO = 0;
@@ -180,7 +216,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
180 /// </summary> 216 /// </summary>
181 private IClientAPI m_currentIncomingClient; 217 private IClientAPI m_currentIncomingClient;
182 218
183 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) 219 public LLUDPServer(
220 IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port,
221 IConfigSource configSource, AgentCircuitManager circuitManager)
184 : base(listenIP, (int)port) 222 : base(listenIP, (int)port)
185 { 223 {
186 #region Environment.TickCount Measurement 224 #region Environment.TickCount Measurement
@@ -202,6 +240,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
202 240
203 m_circuitManager = circuitManager; 241 m_circuitManager = circuitManager;
204 int sceneThrottleBps = 0; 242 int sceneThrottleBps = 0;
243 bool usePools = false;
205 244
206 IConfig config = configSource.Configs["ClientStack.LindenUDP"]; 245 IConfig config = configSource.Configs["ClientStack.LindenUDP"];
207 if (config != null) 246 if (config != null)
@@ -227,6 +266,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
227 m_pausedAckTimeout = 1000 * 300; // 5 minutes 266 m_pausedAckTimeout = 1000 * 300; // 5 minutes
228 } 267 }
229 268
269 // FIXME: This actually only needs to be done once since the PacketPool is shared across all servers.
270 // However, there is no harm in temporarily doing it multiple times.
271 IConfig packetConfig = configSource.Configs["PacketPool"];
272 if (packetConfig != null)
273 {
274 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
275 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
276 usePools = packetConfig.GetBoolean("RecycleBaseUDPPackets", usePools);
277 }
278
230 #region BinaryStats 279 #region BinaryStats
231 config = configSource.Configs["Statistics.Binary"]; 280 config = configSource.Configs["Statistics.Binary"];
232 m_shouldCollectStats = false; 281 m_shouldCollectStats = false;
@@ -254,20 +303,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
254 303
255 m_throttle = new TokenBucket(null, sceneThrottleBps); 304 m_throttle = new TokenBucket(null, sceneThrottleBps);
256 ThrottleRates = new ThrottleRates(configSource); 305 ThrottleRates = new ThrottleRates(configSource);
306
307 if (usePools)
308 EnablePools();
257 } 309 }
258 310
259 public void Start() 311 public void Start()
260 { 312 {
261 if (m_scene == null) 313 StartInbound();
262 throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); 314 StartOutbound();
315
316 m_elapsedMSSinceLastStatReport = Environment.TickCount;
317 }
263 318
319 private void StartInbound()
320 {
264 m_log.InfoFormat( 321 m_log.InfoFormat(
265 "[LLUDPSERVER]: Starting the LLUDP server in {0} mode", 322 "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}",
266 m_asyncPacketHandling ? "asynchronous" : "synchronous"); 323 m_asyncPacketHandling ? "asynchronous" : "synchronous", UsePools);
267 324
268 base.Start(m_recvBufferSize, m_asyncPacketHandling); 325 base.StartInbound(m_recvBufferSize, m_asyncPacketHandling);
269 326
270 // Start the packet processing threads 327 // This thread will process the packets received that are placed on the packetInbox
271 Watchdog.StartThread( 328 Watchdog.StartThread(
272 IncomingPacketHandler, 329 IncomingPacketHandler,
273 string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), 330 string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName),
@@ -276,6 +333,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
276 true, 333 true,
277 GetWatchdogIncomingAlarmData, 334 GetWatchdogIncomingAlarmData,
278 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); 335 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
336 }
337
338 private new void StartOutbound()
339 {
340 m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server");
341
342 base.StartOutbound();
279 343
280 Watchdog.StartThread( 344 Watchdog.StartThread(
281 OutgoingPacketHandler, 345 OutgoingPacketHandler,
@@ -285,8 +349,90 @@ namespace OpenSim.Region.ClientStack.LindenUDP
285 true, 349 true,
286 GetWatchdogOutgoingAlarmData, 350 GetWatchdogOutgoingAlarmData,
287 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); 351 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
352 }
288 353
289 m_elapsedMSSinceLastStatReport = Environment.TickCount; 354 public void Stop()
355 {
356 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
357 base.StopOutbound();
358 base.StopInbound();
359 }
360
361 protected override bool EnablePools()
362 {
363 if (!UsePools)
364 {
365 base.EnablePools();
366
367 m_incomingPacketPool = new Pool<IncomingPacket>(() => new IncomingPacket(), 500);
368
369 return true;
370 }
371
372 return false;
373 }
374
375 protected override bool DisablePools()
376 {
377 if (UsePools)
378 {
379 base.DisablePools();
380
381 StatsManager.DeregisterStat(m_incomingPacketPoolStat);
382
383 // We won't null out the pool to avoid a race condition with code that may be in the middle of using it.
384
385 return true;
386 }
387
388 return false;
389 }
390
391 /// <summary>
392 /// This is a seperate method so that it can be called once we have an m_scene to distinguish different scene
393 /// stats.
394 /// </summary>
395 private void EnablePoolStats()
396 {
397 m_poolCountStat
398 = new Stat(
399 "UDPPacketBufferPoolCount",
400 "Objects within the UDPPacketBuffer pool",
401 "The number of objects currently stored within the UDPPacketBuffer pool",
402 "",
403 "clientstack",
404 m_scene.Name,
405 StatType.Pull,
406 stat => stat.Value = Pool.Count,
407 StatVerbosity.Debug);
408
409 StatsManager.RegisterStat(m_poolCountStat);
410
411 m_incomingPacketPoolStat
412 = new Stat(
413 "IncomingPacketPoolCount",
414 "Objects within incoming packet pool",
415 "The number of objects currently stored within the incoming packet pool",
416 "",
417 "clientstack",
418 m_scene.Name,
419 StatType.Pull,
420 stat => stat.Value = m_incomingPacketPool.Count,
421 StatVerbosity.Debug);
422
423 StatsManager.RegisterStat(m_incomingPacketPoolStat);
424 }
425
426 /// <summary>
427 /// Disables pool stats.
428 /// </summary>
429 private void DisablePoolStats()
430 {
431 StatsManager.DeregisterStat(m_poolCountStat);
432 m_poolCountStat = null;
433
434 StatsManager.DeregisterStat(m_incomingPacketPoolStat);
435 m_incomingPacketPoolStat = null;
290 } 436 }
291 437
292 /// <summary> 438 /// <summary>
@@ -311,12 +457,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
311 m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none"); 457 m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none");
312 } 458 }
313 459
314 public new void Stop()
315 {
316 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
317 base.Stop();
318 }
319
320 public void AddScene(IScene scene) 460 public void AddScene(IScene scene)
321 { 461 {
322 if (m_scene != null) 462 if (m_scene != null)
@@ -333,6 +473,182 @@ namespace OpenSim.Region.ClientStack.LindenUDP
333 473
334 m_scene = (Scene)scene; 474 m_scene = (Scene)scene;
335 m_location = new Location(m_scene.RegionInfo.RegionHandle); 475 m_location = new Location(m_scene.RegionInfo.RegionHandle);
476
477 // XXX: These stats are also pool stats but we register them separately since they are currently not
478 // turned on and off by EnablePools()/DisablePools()
479 StatsManager.RegisterStat(
480 new PercentageStat(
481 "PacketsReused",
482 "Packets reused",
483 "Number of packets reused out of all requests to the packet pool",
484 "clientstack",
485 m_scene.Name,
486 StatType.Pull,
487 stat =>
488 { PercentageStat pstat = (PercentageStat)stat;
489 pstat.Consequent = PacketPool.Instance.PacketsRequested;
490 pstat.Antecedent = PacketPool.Instance.PacketsReused; },
491 StatVerbosity.Debug));
492
493 StatsManager.RegisterStat(
494 new PercentageStat(
495 "PacketDataBlocksReused",
496 "Packet data blocks reused",
497 "Number of data blocks reused out of all requests to the packet pool",
498 "clientstack",
499 m_scene.Name,
500 StatType.Pull,
501 stat =>
502 { PercentageStat pstat = (PercentageStat)stat;
503 pstat.Consequent = PacketPool.Instance.BlocksRequested;
504 pstat.Antecedent = PacketPool.Instance.BlocksReused; },
505 StatVerbosity.Debug));
506
507 StatsManager.RegisterStat(
508 new Stat(
509 "PacketsPoolCount",
510 "Objects within the packet pool",
511 "The number of objects currently stored within the packet pool",
512 "",
513 "clientstack",
514 m_scene.Name,
515 StatType.Pull,
516 stat => stat.Value = PacketPool.Instance.PacketsPooled,
517 StatVerbosity.Debug));
518
519 StatsManager.RegisterStat(
520 new Stat(
521 "PacketDataBlocksPoolCount",
522 "Objects within the packet data block pool",
523 "The number of objects currently stored within the packet data block pool",
524 "",
525 "clientstack",
526 m_scene.Name,
527 StatType.Pull,
528 stat => stat.Value = PacketPool.Instance.BlocksPooled,
529 StatVerbosity.Debug));
530
531 // We delay enabling pool stats to AddScene() instead of Initialize() so that we can distinguish pool stats by
532 // scene name
533 if (UsePools)
534 EnablePoolStats();
535
536 MainConsole.Instance.Commands.AddCommand(
537 "Debug",
538 false,
539 "debug lludp start",
540 "debug lludp start <in|out|all>",
541 "Control LLUDP packet processing.",
542 "No effect if packet processing has already started.\n"
543 + "in - start inbound processing.\n"
544 + "out - start outbound processing.\n"
545 + "all - start in and outbound processing.\n",
546 HandleStartCommand);
547
548 MainConsole.Instance.Commands.AddCommand(
549 "Debug",
550 false,
551 "debug lludp stop",
552 "debug lludp stop <in|out|all>",
553 "Stop LLUDP packet processing.",
554 "No effect if packet processing has already stopped.\n"
555 + "in - stop inbound processing.\n"
556 + "out - stop outbound processing.\n"
557 + "all - stop in and outbound processing.\n",
558 HandleStopCommand);
559
560 MainConsole.Instance.Commands.AddCommand(
561 "Debug",
562 false,
563 "debug lludp pool",
564 "debug lludp pool <on|off>",
565 "Turn object pooling within the lludp component on or off.",
566 HandlePoolCommand);
567
568 MainConsole.Instance.Commands.AddCommand(
569 "Debug",
570 false,
571 "debug lludp status",
572 "debug lludp status",
573 "Return status of LLUDP packet processing.",
574 HandleStatusCommand);
575 }
576
577 private void HandleStartCommand(string module, string[] args)
578 {
579 if (args.Length != 4)
580 {
581 MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>");
582 return;
583 }
584
585 string subCommand = args[3];
586
587 if (subCommand == "in" || subCommand == "all")
588 StartInbound();
589
590 if (subCommand == "out" || subCommand == "all")
591 StartOutbound();
592 }
593
594 private void HandleStopCommand(string module, string[] args)
595 {
596 if (args.Length != 4)
597 {
598 MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>");
599 return;
600 }
601
602 string subCommand = args[3];
603
604 if (subCommand == "in" || subCommand == "all")
605 StopInbound();
606
607 if (subCommand == "out" || subCommand == "all")
608 StopOutbound();
609 }
610
611 private void HandlePoolCommand(string module, string[] args)
612 {
613 if (args.Length != 4)
614 {
615 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
616 return;
617 }
618
619 string enabled = args[3];
620
621 if (enabled == "on")
622 {
623 if (EnablePools())
624 {
625 EnablePoolStats();
626 MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_scene.Name);
627 }
628 }
629 else if (enabled == "off")
630 {
631 if (DisablePools())
632 {
633 DisablePoolStats();
634 MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_scene.Name);
635 }
636 }
637 else
638 {
639 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
640 }
641 }
642
643 private void HandleStatusCommand(string module, string[] args)
644 {
645 MainConsole.Instance.OutputFormat(
646 "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled");
647
648 MainConsole.Instance.OutputFormat(
649 "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled");
650
651 MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off");
336 } 652 }
337 653
338 public bool HandlesRegion(Location x) 654 public bool HandlesRegion(Location x)
@@ -416,6 +732,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
416 byte[] data = packet.ToBytes(); 732 byte[] data = packet.ToBytes();
417 SendPacketData(udpClient, data, packet.Type, category, method); 733 SendPacketData(udpClient, data, packet.Type, category, method);
418 } 734 }
735
736 PacketPool.Instance.ReturnPacket(packet);
419 } 737 }
420 738
421 /// <summary> 739 /// <summary>
@@ -700,7 +1018,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
700 LLUDPClient udpClient = null; 1018 LLUDPClient udpClient = null;
701 Packet packet = null; 1019 Packet packet = null;
702 int packetEnd = buffer.DataLength - 1; 1020 int packetEnd = buffer.DataLength - 1;
703 IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; 1021 IPEndPoint endPoint = (IPEndPoint)buffer.RemoteEndPoint;
704 1022
705 #region Decoding 1023 #region Decoding
706 1024
@@ -710,7 +1028,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
710// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", 1028// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}",
711// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 1029// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
712 1030
713 return; // Drop undersizd packet 1031 return; // Drop undersized packet
714 } 1032 }
715 1033
716 int headerLen = 7; 1034 int headerLen = 7;
@@ -733,7 +1051,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
733 1051
734 try 1052 try
735 { 1053 {
736 packet = Packet.BuildPacket(buffer.Data, ref packetEnd, 1054// packet = Packet.BuildPacket(buffer.Data, ref packetEnd,
1055// // Only allocate a buffer for zerodecoding if the packet is zerocoded
1056// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
1057 // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we
1058 // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all
1059 // bytes are copied out).
1060 packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd,
737 // Only allocate a buffer for zerodecoding if the packet is zerocoded 1061 // Only allocate a buffer for zerodecoding if the packet is zerocoded
738 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); 1062 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
739 } 1063 }
@@ -748,11 +1072,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
748 1072
749 return; // Drop short packet 1073 return; // Drop short packet
750 } 1074 }
751 catch(Exception e) 1075 catch (Exception e)
752 { 1076 {
753 if (m_malformedCount < 100) 1077 if (m_malformedCount < 100)
754 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); 1078 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString());
1079
755 m_malformedCount++; 1080 m_malformedCount++;
1081
756 if ((m_malformedCount % 100000) == 0) 1082 if ((m_malformedCount % 100000) == 0)
757 m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount); 1083 m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount);
758 } 1084 }
@@ -772,7 +1098,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
772 1098
773 // If there is already a client for this endpoint, don't process UseCircuitCode 1099 // If there is already a client for this endpoint, don't process UseCircuitCode
774 IClientAPI client = null; 1100 IClientAPI client = null;
775 if (!m_scene.TryGetClient(address, out client)) 1101 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
776 { 1102 {
777 // UseCircuitCode handling 1103 // UseCircuitCode handling
778 if (packet.Type == PacketType.UseCircuitCode) 1104 if (packet.Type == PacketType.UseCircuitCode)
@@ -780,13 +1106,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
780 // And if there is a UseCircuitCode pending, also drop it 1106 // And if there is a UseCircuitCode pending, also drop it
781 lock (m_pendingCache) 1107 lock (m_pendingCache)
782 { 1108 {
783 if (m_pendingCache.Contains(address)) 1109 if (m_pendingCache.Contains(endPoint))
784 return; 1110 return;
785 1111
786 m_pendingCache.AddOrUpdate(address, new Queue<UDPPacketBuffer>(), 60); 1112 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
787 } 1113 }
788 1114
789 object[] array = new object[] { buffer, packet }; 1115 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1116 // buffer.
1117 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
790 1118
791 Util.FireAndForget(HandleUseCircuitCode, array); 1119 Util.FireAndForget(HandleUseCircuitCode, array);
792 1120
@@ -798,7 +1126,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
798 lock (m_pendingCache) 1126 lock (m_pendingCache)
799 { 1127 {
800 Queue<UDPPacketBuffer> queue; 1128 Queue<UDPPacketBuffer> queue;
801 if (m_pendingCache.TryGetValue(address, out queue)) 1129 if (m_pendingCache.TryGetValue(endPoint, out queue))
802 { 1130 {
803 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type); 1131 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
804 queue.Enqueue(buffer); 1132 queue.Enqueue(buffer);
@@ -834,6 +1162,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
834 // Handle appended ACKs 1162 // Handle appended ACKs
835 if (packet.Header.AppendedAcks && packet.Header.AckList != null) 1163 if (packet.Header.AppendedAcks && packet.Header.AckList != null)
836 { 1164 {
1165// m_log.DebugFormat(
1166// "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}",
1167// packet.Header.AckList.Length, client.Name, m_scene.Name);
1168
837 for (int i = 0; i < packet.Header.AckList.Length; i++) 1169 for (int i = 0; i < packet.Header.AckList.Length; i++)
838 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); 1170 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
839 } 1171 }
@@ -843,6 +1175,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
843 { 1175 {
844 PacketAckPacket ackPacket = (PacketAckPacket)packet; 1176 PacketAckPacket ackPacket = (PacketAckPacket)packet;
845 1177
1178// m_log.DebugFormat(
1179// "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}",
1180// ackPacket.Packets.Length, client.Name, m_scene.Name);
1181
846 for (int i = 0; i < ackPacket.Packets.Length; i++) 1182 for (int i = 0; i < ackPacket.Packets.Length; i++)
847 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); 1183 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
848 1184
@@ -856,6 +1192,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
856 1192
857 if (packet.Header.Reliable) 1193 if (packet.Header.Reliable)
858 { 1194 {
1195// m_log.DebugFormat(
1196// "[LLUDPSERVER]: Adding ack request for {0} {1} from {2} in {3}",
1197// packet.Type, packet.Header.Sequence, client.Name, m_scene.Name);
1198
859 udpClient.PendingAcks.Enqueue(packet.Header.Sequence); 1199 udpClient.PendingAcks.Enqueue(packet.Header.Sequence);
860 1200
861 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, 1201 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
@@ -902,6 +1242,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
902 1242
903 if (packet.Type == PacketType.StartPingCheck) 1243 if (packet.Type == PacketType.StartPingCheck)
904 { 1244 {
1245// m_log.DebugFormat("[LLUDPSERVER]: Handling ping from {0} in {1}", client.Name, m_scene.Name);
1246
905 // We don't need to do anything else with ping checks 1247 // We don't need to do anything else with ping checks
906 StartPingCheckPacket startPing = (StartPingCheckPacket)packet; 1248 StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
907 CompletePing(udpClient, startPing.PingID.PingID); 1249 CompletePing(udpClient, startPing.PingID.PingID);
@@ -921,13 +1263,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
921 1263
922 #endregion Ping Check Handling 1264 #endregion Ping Check Handling
923 1265
1266 IncomingPacket incomingPacket;
1267
924 // Inbox insertion 1268 // Inbox insertion
925 if (packet.Type == PacketType.AgentUpdate || 1269 if (UsePools)
926 packet.Type == PacketType.ChatFromViewer) 1270 {
927 packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet)); 1271 incomingPacket = m_incomingPacketPool.GetObject();
1272 incomingPacket.Client = (LLClientView)client;
1273 incomingPacket.Packet = packet;
1274 }
1275 else
1276 {
1277 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1278 }
1279
1280 if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1281 incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1282 packetInbox.EnqueueHigh(incomingPacket);
928 else 1283 else
929 packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet)); 1284 packetInbox.EnqueueLow(incomingPacket);
930// packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
931 } 1285 }
932 1286
933 #region BinaryStats 1287 #region BinaryStats
@@ -1013,21 +1367,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1013 1367
1014 private void HandleUseCircuitCode(object o) 1368 private void HandleUseCircuitCode(object o)
1015 { 1369 {
1016 IPEndPoint remoteEndPoint = null; 1370 IPEndPoint endPoint = null;
1017 IClientAPI client = null; 1371 IClientAPI client = null;
1018 1372
1019 try 1373 try
1020 { 1374 {
1021 // DateTime startTime = DateTime.Now; 1375 // DateTime startTime = DateTime.Now;
1022 object[] array = (object[])o; 1376 object[] array = (object[])o;
1023 UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; 1377 endPoint = (IPEndPoint)array[0];
1024 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; 1378 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
1025 1379
1026 m_log.DebugFormat( 1380 m_log.DebugFormat(
1027 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", 1381 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
1028 uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint); 1382 uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint);
1029
1030 remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
1031 1383
1032 AuthenticateResponse sessionInfo; 1384 AuthenticateResponse sessionInfo;
1033 if (IsClientAuthorized(uccp, out sessionInfo)) 1385 if (IsClientAuthorized(uccp, out sessionInfo))
@@ -1038,13 +1390,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1038 uccp.CircuitCode.Code, 1390 uccp.CircuitCode.Code,
1039 uccp.CircuitCode.ID, 1391 uccp.CircuitCode.ID,
1040 uccp.CircuitCode.SessionID, 1392 uccp.CircuitCode.SessionID,
1041 remoteEndPoint, 1393 endPoint,
1042 sessionInfo); 1394 sessionInfo);
1043 1395
1044 // Send ack straight away to let the viewer know that the connection is active. 1396 // Send ack straight away to let the viewer know that the connection is active.
1045 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use 1397 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use
1046 // circuit code to the existing child agent. This is not particularly obvious. 1398 // circuit code to the existing child agent. This is not particularly obvious.
1047 SendAckImmediate(remoteEndPoint, uccp.Header.Sequence); 1399 SendAckImmediate(endPoint, uccp.Header.Sequence);
1048 1400
1049 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1401 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1050 if (client != null) 1402 if (client != null)
@@ -1058,12 +1410,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1058 1410
1059 lock (m_pendingCache) 1411 lock (m_pendingCache)
1060 { 1412 {
1061 if (!m_pendingCache.TryGetValue(remoteEndPoint, out queue)) 1413 if (!m_pendingCache.TryGetValue(endPoint, out queue))
1062 { 1414 {
1063 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); 1415 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1064 return; 1416 return;
1065 } 1417 }
1066 m_pendingCache.Remove(remoteEndPoint); 1418 m_pendingCache.Remove(endPoint);
1067 } 1419 }
1068 1420
1069 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); 1421 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
@@ -1081,9 +1433,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1081 // Don't create clients for unauthorized requesters. 1433 // Don't create clients for unauthorized requesters.
1082 m_log.WarnFormat( 1434 m_log.WarnFormat(
1083 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1435 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1084 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint); 1436 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
1085 lock (m_pendingCache) 1437 lock (m_pendingCache)
1086 m_pendingCache.Remove(remoteEndPoint); 1438 m_pendingCache.Remove(endPoint);
1087 } 1439 }
1088 1440
1089 // m_log.DebugFormat( 1441 // m_log.DebugFormat(
@@ -1095,7 +1447,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1095 { 1447 {
1096 m_log.ErrorFormat( 1448 m_log.ErrorFormat(
1097 "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", 1449 "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}",
1098 remoteEndPoint != null ? remoteEndPoint.ToString() : "n/a", 1450 endPoint != null ? endPoint.ToString() : "n/a",
1099 client != null ? client.Name : "unknown", 1451 client != null ? client.Name : "unknown",
1100 client != null ? client.AgentId.ToString() : "unknown", 1452 client != null ? client.AgentId.ToString() : "unknown",
1101 e.Message, 1453 e.Message,
@@ -1160,20 +1512,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1160 { 1512 {
1161 IClientAPI client = null; 1513 IClientAPI client = null;
1162 1514
1163 // In priciple there shouldn't be more than one thread here, ever. 1515 // We currently synchronize this code across the whole scene to avoid issues such as
1164 // But in case that happens, we need to synchronize this piece of code 1516 // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done
1165 // because it's too important 1517 // consistently, this lock could probably be removed.
1166 lock (this) 1518 lock (this)
1167 { 1519 {
1168 if (!m_scene.TryGetClient(agentID, out client)) 1520 if (!m_scene.TryGetClient(agentID, out client))
1169 { 1521 {
1170 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); 1522 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
1171 1523
1172 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 1524 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
1173 client.OnLogout += LogoutHandler; 1525 client.OnLogout += LogoutHandler;
1174 1526
1175 ((LLClientView)client).DisableFacelights = m_disableFacelights; 1527 ((LLClientView)client).DisableFacelights = m_disableFacelights;
1176 1528
1177 client.Start(); 1529 client.Start();
1178 } 1530 }
1179 } 1531 }
@@ -1212,7 +1564,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1212 // on to en-US to avoid number parsing issues 1564 // on to en-US to avoid number parsing issues
1213 Culture.SetCurrentCulture(); 1565 Culture.SetCurrentCulture();
1214 1566
1215 while (base.IsRunning) 1567 while (IsRunningInbound)
1216 { 1568 {
1217 m_scene.ThreadAlive(1); 1569 m_scene.ThreadAlive(1);
1218 try 1570 try
@@ -1228,7 +1580,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1228 } 1580 }
1229 1581
1230 if (packetInbox.Dequeue(100, ref incomingPacket)) 1582 if (packetInbox.Dequeue(100, ref incomingPacket))
1583 {
1231 ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket); 1584 ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket);
1585
1586 if (UsePools)
1587 m_incomingPacketPool.ReturnObject(incomingPacket);
1588 }
1232 } 1589 }
1233 catch (Exception ex) 1590 catch (Exception ex)
1234 { 1591 {
@@ -1255,7 +1612,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1255 // Action generic every round 1612 // Action generic every round
1256 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler; 1613 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
1257 1614
1258 while (base.IsRunning) 1615 while (base.IsRunningOutbound)
1259 { 1616 {
1260 m_scene.ThreadAlive(2); 1617 m_scene.ThreadAlive(2);
1261 try 1618 try
@@ -1383,6 +1740,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1383 private int npacksSent = 0; 1740 private int npacksSent = 0;
1384 private int npackNotSent = 0; 1741 private int npackNotSent = 0;
1385 1742
1743 /// <summary>
1744 /// Number of inbound packets processed since startup.
1745 /// </summary>
1746 public long IncomingPacketsProcessed { get; private set; }
1747
1386 private void MonitoredClientOutgoingPacketHandler(IClientAPI client) 1748 private void MonitoredClientOutgoingPacketHandler(IClientAPI client)
1387 { 1749 {
1388 nticks++; 1750 nticks++;
@@ -1442,7 +1804,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1442 npacksSent++; 1804 npacksSent++;
1443 } 1805 }
1444 else 1806 else
1807 {
1445 npackNotSent++; 1808 npackNotSent++;
1809 }
1446 1810
1447 watch2.Stop(); 1811 watch2.Stop();
1448 avgDequeueTicks = (nticks - 1) / (float)nticks * avgDequeueTicks + (watch2.ElapsedTicks / (float)nticks); 1812 avgDequeueTicks = (nticks - 1) / (float)nticks * avgDequeueTicks + (watch2.ElapsedTicks / (float)nticks);
@@ -1450,7 +1814,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1450 1814
1451 } 1815 }
1452 else 1816 else
1817 {
1453 m_log.WarnFormat("[LLUDPSERVER]: Client is not connected"); 1818 m_log.WarnFormat("[LLUDPSERVER]: Client is not connected");
1819 }
1454 } 1820 }
1455 } 1821 }
1456 catch (Exception ex) 1822 catch (Exception ex)
@@ -1514,6 +1880,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1514// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 1880// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
1515// packet.Type, client.Name, m_scene.RegionInfo.RegionName); 1881// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
1516// } 1882// }
1883
1884 IncomingPacketsProcessed++;
1517 } 1885 }
1518 1886
1519 protected void LogoutHandler(IClientAPI client) 1887 protected void LogoutHandler(IClientAPI client)
@@ -1523,7 +1891,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1523 if (!client.IsLoggingOut) 1891 if (!client.IsLoggingOut)
1524 { 1892 {
1525 client.IsLoggingOut = true; 1893 client.IsLoggingOut = true;
1526 client.Close(false); 1894 client.Close(false, false);
1527 } 1895 }
1528 } 1896 }
1529 } 1897 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index cfe7c9d..2aeb4cc 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -30,6 +30,8 @@ using System.Net;
30using System.Net.Sockets; 30using System.Net.Sockets;
31using System.Threading; 31using System.Threading;
32using log4net; 32using log4net;
33using OpenSim.Framework;
34using OpenSim.Framework.Monitoring;
33 35
34namespace OpenMetaverse 36namespace OpenMetaverse
35{ 37{
@@ -58,17 +60,29 @@ namespace OpenMetaverse
58 /// <summary>Flag to process packets asynchronously or synchronously</summary> 60 /// <summary>Flag to process packets asynchronously or synchronously</summary>
59 private bool m_asyncPacketHandling; 61 private bool m_asyncPacketHandling;
60 62
61 /// <summary>The all important shutdown flag</summary> 63 /// <summary>
62 private volatile bool m_shutdownFlag = true; 64 /// Are we to use object pool(s) to reduce memory churn when receiving data?
65 /// </summary>
66 public bool UsePools { get; protected set; }
67
68 /// <summary>
69 /// Pool to use for handling data. May be null if UsePools = false;
70 /// </summary>
71 protected OpenSim.Framework.Pool<UDPPacketBuffer> Pool { get; private set; }
72
73 /// <summary>Returns true if the server is currently listening for inbound packets, otherwise false</summary>
74 public bool IsRunningInbound { get; private set; }
63 75
64 /// <summary>Returns true if the server is currently listening, otherwise false</summary> 76 /// <summary>Returns true if the server is currently sending outbound packets, otherwise false</summary>
65 public bool IsRunning { get { return !m_shutdownFlag; } } 77 /// <remarks>If IsRunningOut = false, then any request to send a packet is simply dropped.</remarks>
78 public bool IsRunningOutbound { get; private set; }
66 79
67 /// <summary> 80 /// <summary>
68 /// Default constructor 81 /// Default constructor
69 /// </summary> 82 /// </summary>
70 /// <param name="bindAddress">Local IP address to bind the server to</param> 83 /// <param name="bindAddress">Local IP address to bind the server to</param>
71 /// <param name="port">Port to listening for incoming UDP packets on</param> 84 /// <param name="port">Port to listening for incoming UDP packets on</param>
85 /// /// <param name="usePool">Are we to use an object pool to get objects for handing inbound data?</param>
72 public OpenSimUDPBase(IPAddress bindAddress, int port) 86 public OpenSimUDPBase(IPAddress bindAddress, int port)
73 { 87 {
74 m_localBindAddress = bindAddress; 88 m_localBindAddress = bindAddress;
@@ -76,7 +90,7 @@ namespace OpenMetaverse
76 } 90 }
77 91
78 /// <summary> 92 /// <summary>
79 /// Start the UDP server 93 /// Start inbound UDP packet handling.
80 /// </summary> 94 /// </summary>
81 /// <param name="recvBufferSize">The size of the receive buffer for 95 /// <param name="recvBufferSize">The size of the receive buffer for
82 /// the UDP socket. This value is passed up to the operating system 96 /// the UDP socket. This value is passed up to the operating system
@@ -91,11 +105,11 @@ namespace OpenMetaverse
91 /// manner (not throwing an exception when the remote side resets the 105 /// manner (not throwing an exception when the remote side resets the
92 /// connection). This call is ignored on Mono where the flag is not 106 /// connection). This call is ignored on Mono where the flag is not
93 /// necessary</remarks> 107 /// necessary</remarks>
94 public void Start(int recvBufferSize, bool asyncPacketHandling) 108 public void StartInbound(int recvBufferSize, bool asyncPacketHandling)
95 { 109 {
96 m_asyncPacketHandling = asyncPacketHandling; 110 m_asyncPacketHandling = asyncPacketHandling;
97 111
98 if (m_shutdownFlag) 112 if (!IsRunningInbound)
99 { 113 {
100 const int SIO_UDP_CONNRESET = -1744830452; 114 const int SIO_UDP_CONNRESET = -1744830452;
101 115
@@ -123,8 +137,7 @@ namespace OpenMetaverse
123 137
124 m_udpSocket.Bind(ipep); 138 m_udpSocket.Bind(ipep);
125 139
126 // we're not shutting down, we're starting up 140 IsRunningInbound = true;
127 m_shutdownFlag = false;
128 141
129 // kick off an async receive. The Start() method will return, the 142 // kick off an async receive. The Start() method will return, the
130 // actual receives will occur asynchronously and will be caught in 143 // actual receives will occur asynchronously and will be caught in
@@ -134,28 +147,69 @@ namespace OpenMetaverse
134 } 147 }
135 148
136 /// <summary> 149 /// <summary>
137 /// Stops the UDP server 150 /// Start outbound UDP packet handling.
138 /// </summary> 151 /// </summary>
139 public void Stop() 152 public void StartOutbound()
140 { 153 {
141 if (!m_shutdownFlag) 154 IsRunningOutbound = true;
155 }
156
157 public void StopInbound()
158 {
159 if (IsRunningInbound)
142 { 160 {
143 // wait indefinitely for a writer lock. Once this is called, the .NET runtime 161 // 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 162 // 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 163 // threads. Once we have the lock, we set IsRunningInbound = false to inform the other
146 // threads that the socket is closed. 164 // threads that the socket is closed.
147 m_shutdownFlag = true; 165 IsRunningInbound = false;
148 m_udpSocket.Close(); 166 m_udpSocket.Close();
149 } 167 }
150 } 168 }
151 169
170 public void StopOutbound()
171 {
172 IsRunningOutbound = false;
173 }
174
175 protected virtual bool EnablePools()
176 {
177 if (!UsePools)
178 {
179 Pool = new Pool<UDPPacketBuffer>(() => new UDPPacketBuffer(), 500);
180
181 UsePools = true;
182
183 return true;
184 }
185
186 return false;
187 }
188
189 protected virtual bool DisablePools()
190 {
191 if (UsePools)
192 {
193 UsePools = false;
194
195 // We won't null out the pool to avoid a race condition with code that may be in the middle of using it.
196
197 return true;
198 }
199
200 return false;
201 }
202
152 private void AsyncBeginReceive() 203 private void AsyncBeginReceive()
153 { 204 {
154 // allocate a packet buffer 205 UDPPacketBuffer buf;
155 //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut(); 206
156 UDPPacketBuffer buf = new UDPPacketBuffer(); 207 if (UsePools)
208 buf = Pool.GetObject();
209 else
210 buf = new UDPPacketBuffer();
157 211
158 if (!m_shutdownFlag) 212 if (IsRunningInbound)
159 { 213 {
160 try 214 try
161 { 215 {
@@ -208,7 +262,7 @@ namespace OpenMetaverse
208 { 262 {
209 // Asynchronous receive operations will complete here through the call 263 // Asynchronous receive operations will complete here through the call
210 // to AsyncBeginReceive 264 // to AsyncBeginReceive
211 if (!m_shutdownFlag) 265 if (IsRunningInbound)
212 { 266 {
213 // Asynchronous mode will start another receive before the 267 // Asynchronous mode will start another receive before the
214 // callback for this packet is even fired. Very parallel :-) 268 // callback for this packet is even fired. Very parallel :-)
@@ -217,8 +271,6 @@ namespace OpenMetaverse
217 271
218 // get the buffer that was created in AsyncBeginReceive 272 // get the buffer that was created in AsyncBeginReceive
219 // this is the received data 273 // this is the received data
220 //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState;
221 //UDPPacketBuffer buffer = wrappedBuffer.Instance;
222 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; 274 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
223 275
224 try 276 try
@@ -235,7 +287,8 @@ namespace OpenMetaverse
235 catch (ObjectDisposedException) { } 287 catch (ObjectDisposedException) { }
236 finally 288 finally
237 { 289 {
238 //wrappedBuffer.Dispose(); 290 if (UsePools)
291 Pool.ReturnObject(buffer);
239 292
240 // Synchronous mode waits until the packet callback completes 293 // Synchronous mode waits until the packet callback completes
241 // before starting the receive to fetch another packet 294 // before starting the receive to fetch another packet
@@ -248,7 +301,7 @@ namespace OpenMetaverse
248 301
249 public void AsyncBeginSend(UDPPacketBuffer buf) 302 public void AsyncBeginSend(UDPPacketBuffer buf)
250 { 303 {
251 if (!m_shutdownFlag) 304 if (IsRunningOutbound)
252 { 305 {
253 try 306 try
254 { 307 {
@@ -277,4 +330,4 @@ namespace OpenMetaverse
277 catch (ObjectDisposedException) { } 330 catch (ObjectDisposedException) { }
278 } 331 }
279 } 332 }
280} 333} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs
new file mode 100644
index 0000000..1fdc410
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs
@@ -0,0 +1,306 @@
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.Reflection;
31using OpenMetaverse;
32using OpenMetaverse.Packets;
33using log4net;
34using OpenSim.Framework.Monitoring;
35
36namespace OpenSim.Region.ClientStack.LindenUDP
37{
38 public sealed class PacketPool
39 {
40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41
42 private static readonly PacketPool instance = new PacketPool();
43
44 /// <summary>
45 /// Pool of packets available for reuse.
46 /// </summary>
47 private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>();
48
49 private static Dictionary<Type, Stack<Object>> DataBlocks = new Dictionary<Type, Stack<Object>>();
50
51 public static PacketPool Instance
52 {
53 get { return instance; }
54 }
55
56 public bool RecyclePackets { get; set; }
57
58 public bool RecycleDataBlocks { get; set; }
59
60 /// <summary>
61 /// The number of packets pooled
62 /// </summary>
63 public int PacketsPooled
64 {
65 get
66 {
67 lock (pool)
68 return pool.Count;
69 }
70 }
71
72 /// <summary>
73 /// The number of blocks pooled.
74 /// </summary>
75 public int BlocksPooled
76 {
77 get
78 {
79 lock (DataBlocks)
80 return DataBlocks.Count;
81 }
82 }
83
84 /// <summary>
85 /// Number of packets requested.
86 /// </summary>
87 public long PacketsRequested { get; private set; }
88
89 /// <summary>
90 /// Number of packets reused.
91 /// </summary>
92 public long PacketsReused { get; private set; }
93
94 /// <summary>
95 /// Number of packet blocks requested.
96 /// </summary>
97 public long BlocksRequested { get; private set; }
98
99 /// <summary>
100 /// Number of packet blocks reused.
101 /// </summary>
102 public long BlocksReused { get; private set; }
103
104 private PacketPool()
105 {
106 // defaults
107 RecyclePackets = true;
108 RecycleDataBlocks = true;
109 }
110
111 /// <summary>
112 /// Gets a packet of the given type.
113 /// </summary>
114 /// <param name='type'></param>
115 /// <returns>Guaranteed to always return a packet, whether from the pool or newly constructed.</returns>
116 public Packet GetPacket(PacketType type)
117 {
118 PacketsRequested++;
119
120 Packet packet;
121
122 if (!RecyclePackets)
123 return Packet.BuildPacket(type);
124
125 lock (pool)
126 {
127 if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0)
128 {
129// m_log.DebugFormat("[PACKETPOOL]: Building {0} packet", type);
130
131 // Creating a new packet if we cannot reuse an old package
132 packet = Packet.BuildPacket(type);
133 }
134 else
135 {
136// m_log.DebugFormat("[PACKETPOOL]: Pulling {0} packet", type);
137
138 // Recycle old packages
139 PacketsReused++;
140
141 packet = pool[type].Pop();
142 }
143 }
144
145 return packet;
146 }
147
148 // private byte[] decoded_header = new byte[10];
149 private static PacketType GetType(byte[] bytes)
150 {
151 byte[] decoded_header = new byte[10 + 8];
152 ushort id;
153 PacketFrequency freq;
154
155 if ((bytes[0] & Helpers.MSG_ZEROCODED) != 0)
156 {
157 Helpers.ZeroDecode(bytes, 16, decoded_header);
158 }
159 else
160 {
161 Buffer.BlockCopy(bytes, 0, decoded_header, 0, 10);
162 }
163
164 if (decoded_header[6] == 0xFF)
165 {
166 if (decoded_header[7] == 0xFF)
167 {
168 id = (ushort) ((decoded_header[8] << 8) + decoded_header[9]);
169 freq = PacketFrequency.Low;
170 }
171 else
172 {
173 id = decoded_header[7];
174 freq = PacketFrequency.Medium;
175 }
176 }
177 else
178 {
179 id = decoded_header[6];
180 freq = PacketFrequency.High;
181 }
182
183 return Packet.GetType(id, freq);
184 }
185
186 public Packet GetPacket(byte[] bytes, ref int packetEnd, byte[] zeroBuffer)
187 {
188 PacketType type = GetType(bytes);
189
190// Array.Clear(zeroBuffer, 0, zeroBuffer.Length);
191
192 int i = 0;
193 Packet packet = GetPacket(type);
194 if (packet == null)
195 m_log.WarnFormat("[PACKETPOOL]: Failed to get packet of type {0}", type);
196 else
197 packet.FromBytes(bytes, ref i, ref packetEnd, zeroBuffer);
198
199 return packet;
200 }
201
202 /// <summary>
203 /// Return a packet to the packet pool
204 /// </summary>
205 /// <param name="packet"></param>
206 public void ReturnPacket(Packet packet)
207 {
208 if (RecycleDataBlocks)
209 {
210 switch (packet.Type)
211 {
212 case PacketType.ObjectUpdate:
213 ObjectUpdatePacket oup = (ObjectUpdatePacket)packet;
214
215 foreach (ObjectUpdatePacket.ObjectDataBlock oupod in oup.ObjectData)
216 ReturnDataBlock<ObjectUpdatePacket.ObjectDataBlock>(oupod);
217
218 oup.ObjectData = null;
219 break;
220
221 case PacketType.ImprovedTerseObjectUpdate:
222 ImprovedTerseObjectUpdatePacket itoup = (ImprovedTerseObjectUpdatePacket)packet;
223
224 foreach (ImprovedTerseObjectUpdatePacket.ObjectDataBlock itoupod in itoup.ObjectData)
225 ReturnDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(itoupod);
226
227 itoup.ObjectData = null;
228 break;
229 }
230 }
231
232 if (RecyclePackets)
233 {
234 switch (packet.Type)
235 {
236 // List pooling packets here
237 case PacketType.AgentUpdate:
238 case PacketType.PacketAck:
239 case PacketType.ObjectUpdate:
240 case PacketType.ImprovedTerseObjectUpdate:
241 lock (pool)
242 {
243 PacketType type = packet.Type;
244
245 if (!pool.ContainsKey(type))
246 {
247 pool[type] = new Stack<Packet>();
248 }
249
250 if ((pool[type]).Count < 50)
251 {
252// m_log.DebugFormat("[PACKETPOOL]: Pushing {0} packet", type);
253
254 pool[type].Push(packet);
255 }
256 }
257 break;
258
259 // Other packets wont pool
260 default:
261 return;
262 }
263 }
264 }
265
266 public T GetDataBlock<T>() where T: new()
267 {
268 lock (DataBlocks)
269 {
270 BlocksRequested++;
271
272 Stack<Object> s;
273
274 if (DataBlocks.TryGetValue(typeof(T), out s))
275 {
276 if (s.Count > 0)
277 {
278 BlocksReused++;
279 return (T)s.Pop();
280 }
281 }
282 else
283 {
284 DataBlocks[typeof(T)] = new Stack<Object>();
285 }
286
287 return new T();
288 }
289 }
290
291 public void ReturnDataBlock<T>(T block) where T: new()
292 {
293 if (block == null)
294 return;
295
296 lock (DataBlocks)
297 {
298 if (!DataBlocks.ContainsKey(typeof(T)))
299 DataBlocks[typeof(T)] = new Stack<Object>();
300
301 if (DataBlocks[typeof(T)].Count < 50)
302 DataBlocks[typeof(T)].Push(block);
303 }
304 }
305 }
306} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..af2f6f8
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.ClientStack.LindenUDP")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("9d3dbc6b-9d85-483b-af48-c1dfc261b7ac")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
index 109a8e1..556df30 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
@@ -43,7 +43,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
43 /// This will contain basic tests for the LindenUDP client stack 43 /// This will contain basic tests for the LindenUDP client stack
44 /// </summary> 44 /// </summary>
45 [TestFixture] 45 [TestFixture]
46 public class BasicCircuitTests 46 public class BasicCircuitTests : OpenSimTestCase
47 { 47 {
48 private Scene m_scene; 48 private Scene m_scene;
49 private TestLLUDPServer m_udpServer; 49 private TestLLUDPServer m_udpServer;
@@ -65,8 +65,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
65 } 65 }
66 66
67 [SetUp] 67 [SetUp]
68 public void SetUp() 68 public override void SetUp()
69 { 69 {
70 base.SetUp();
70 m_scene = new SceneHelpers().SetupScene(); 71 m_scene = new SceneHelpers().SetupScene();
71 } 72 }
72 73
@@ -143,7 +144,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
143 public void TestAddClient() 144 public void TestAddClient()
144 { 145 {
145 TestHelpers.InMethod(); 146 TestHelpers.InMethod();
146// XmlConfigurator.Configure(); 147// TestHelpers.EnableLogging();
147 148
148 AddUdpServer(); 149 AddUdpServer();
149 150