aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/Caps
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/Caps')
-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
15 files changed, 756 insertions, 157 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