aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs140
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs6
-rw-r--r--OpenSim/Framework/IClientAPI.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs362
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs187
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs11
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs13
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs5
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs1
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs2
-rw-r--r--OpenSim/Tests/Common/Mock/TestClient.cs2
12 files changed, 697 insertions, 37 deletions
diff --git a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
index 720640e..da59294 100644
--- a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
@@ -45,16 +45,53 @@ namespace OpenSim.Capabilities.Handlers
45{ 45{
46 public class GetMeshHandler 46 public class GetMeshHandler
47 { 47 {
48// private static readonly ILog m_log = 48 private static readonly ILog m_log =
49// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 50
51 private IAssetService m_assetService; 51 private IAssetService m_assetService;
52 52
53 public const string DefaultFormat = "vnd.ll.mesh";
54
53 public GetMeshHandler(IAssetService assService) 55 public GetMeshHandler(IAssetService assService)
54 { 56 {
55 m_assetService = assService; 57 m_assetService = assService;
56 } 58 }
59 public Hashtable Handle(Hashtable request)
60 {
61 Hashtable ret = new Hashtable();
62 ret["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
63 ret["content_type"] = "text/plain";
64 ret["keepalive"] = false;
65 ret["reusecontext"] = false;
66 ret["int_bytes"] = 0;
67 string MeshStr = (string)request["mesh_id"];
68
69
70 //m_log.DebugFormat("[GETMESH]: called {0}", MeshStr);
71
72 if (m_assetService == null)
73 {
74 m_log.Error("[GETMESH]: Cannot fetch mesh " + MeshStr + " without an asset service");
75 }
76
77 UUID meshID;
78 if (!String.IsNullOrEmpty(MeshStr) && UUID.TryParse(MeshStr, out meshID))
79 {
80 // m_log.DebugFormat("[GETMESH]: Received request for mesh id {0}", meshID);
57 81
82
83 ret = ProcessGetMesh(request, UUID.Zero, null);
84
85
86 }
87 else
88 {
89 m_log.Warn("[GETMESH]: Failed to parse a mesh_id from GetMesh request: " + (string)request["uri"]);
90 }
91
92
93 return ret;
94 }
58 public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap) 95 public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap)
59 { 96 {
60 Hashtable responsedata = new Hashtable(); 97 Hashtable responsedata = new Hashtable();
@@ -62,6 +99,7 @@ namespace OpenSim.Capabilities.Handlers
62 responsedata["content_type"] = "text/plain"; 99 responsedata["content_type"] = "text/plain";
63 responsedata["keepalive"] = false; 100 responsedata["keepalive"] = false;
64 responsedata["str_response_string"] = "Request wasn't what was expected"; 101 responsedata["str_response_string"] = "Request wasn't what was expected";
102 responsedata["reusecontext"] = false;
65 103
66 string meshStr = string.Empty; 104 string meshStr = string.Empty;
67 105
@@ -77,6 +115,7 @@ namespace OpenSim.Capabilities.Handlers
77 responsedata["content_type"] = "text/plain"; 115 responsedata["content_type"] = "text/plain";
78 responsedata["keepalive"] = false; 116 responsedata["keepalive"] = false;
79 responsedata["str_response_string"] = "The asset service is unavailable. So is your mesh."; 117 responsedata["str_response_string"] = "The asset service is unavailable. So is your mesh.";
118 responsedata["reusecontext"] = false;
80 return responsedata; 119 return responsedata;
81 } 120 }
82 121
@@ -86,9 +125,83 @@ namespace OpenSim.Capabilities.Handlers
86 { 125 {
87 if (mesh.Type == (SByte)AssetType.Mesh) 126 if (mesh.Type == (SByte)AssetType.Mesh)
88 { 127 {
89 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data); 128
90 responsedata["content_type"] = "application/vnd.ll.mesh"; 129 Hashtable headers = new Hashtable();
91 responsedata["int_response_code"] = 200; 130 responsedata["headers"] = headers;
131
132 string range = String.Empty;
133
134 if (((Hashtable)request["headers"])["range"] != null)
135 range = (string)((Hashtable)request["headers"])["range"];
136
137 else if (((Hashtable)request["headers"])["Range"] != null)
138 range = (string)((Hashtable)request["headers"])["Range"];
139
140 if (!String.IsNullOrEmpty(range)) // Mesh Asset LOD // Physics
141 {
142 // Range request
143 int start, end;
144 if (TryParseRange(range, out start, out end))
145 {
146 // Before clamping start make sure we can satisfy it in order to avoid
147 // sending back the last byte instead of an error status
148 if (start >= mesh.Data.Length)
149 {
150 responsedata["int_response_code"] = 404; //501; //410; //404;
151 responsedata["content_type"] = "text/plain";
152 responsedata["keepalive"] = false;
153 responsedata["str_response_string"] = "This range doesnt exist.";
154 responsedata["reusecontext"] = false;
155 return responsedata;
156 }
157 else
158 {
159 end = Utils.Clamp(end, 0, mesh.Data.Length - 1);
160 start = Utils.Clamp(start, 0, end);
161 int len = end - start + 1;
162
163 //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
164
165
166
167 if (start == 0 && len == mesh.Data.Length) // well redudante maybe
168 {
169 responsedata["int_response_code"] = (int) System.Net.HttpStatusCode.OK;
170 responsedata["bin_response_data"] = mesh.Data;
171 responsedata["int_bytes"] = mesh.Data.Length;
172 responsedata["reusecontext"] = false;
173 }
174 else
175 {
176 responsedata["int_response_code"] =
177 (int) System.Net.HttpStatusCode.PartialContent;
178 headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end,
179 mesh.Data.Length);
180
181 byte[] d = new byte[len];
182 Array.Copy(mesh.Data, start, d, 0, len);
183 responsedata["bin_response_data"] = d;
184 responsedata["int_bytes"] = len;
185 responsedata["reusecontext"] = false;
186 }
187 }
188 }
189 else
190 {
191 m_log.Warn("[GETMESH]: Failed to parse a range from GetMesh request, sending full asset: " + (string)request["uri"]);
192 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
193 responsedata["content_type"] = "application/vnd.ll.mesh";
194 responsedata["int_response_code"] = 200;
195 responsedata["reusecontext"] = false;
196 }
197 }
198 else
199 {
200 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
201 responsedata["content_type"] = "application/vnd.ll.mesh";
202 responsedata["int_response_code"] = 200;
203 responsedata["reusecontext"] = false;
204 }
92 } 205 }
93 // Optionally add additional mesh types here 206 // Optionally add additional mesh types here
94 else 207 else
@@ -97,6 +210,7 @@ namespace OpenSim.Capabilities.Handlers
97 responsedata["content_type"] = "text/plain"; 210 responsedata["content_type"] = "text/plain";
98 responsedata["keepalive"] = false; 211 responsedata["keepalive"] = false;
99 responsedata["str_response_string"] = "Unfortunately, this asset isn't a mesh."; 212 responsedata["str_response_string"] = "Unfortunately, this asset isn't a mesh.";
213 responsedata["reusecontext"] = false;
100 return responsedata; 214 return responsedata;
101 } 215 }
102 } 216 }
@@ -106,11 +220,27 @@ namespace OpenSim.Capabilities.Handlers
106 responsedata["content_type"] = "text/plain"; 220 responsedata["content_type"] = "text/plain";
107 responsedata["keepalive"] = false; 221 responsedata["keepalive"] = false;
108 responsedata["str_response_string"] = "Your Mesh wasn't found. Sorry!"; 222 responsedata["str_response_string"] = "Your Mesh wasn't found. Sorry!";
223 responsedata["reusecontext"] = false;
109 return responsedata; 224 return responsedata;
110 } 225 }
111 } 226 }
112 227
113 return responsedata; 228 return responsedata;
114 } 229 }
230 private bool TryParseRange(string header, out int start, out int end)
231 {
232 if (header.StartsWith("bytes="))
233 {
234 string[] rangeValues = header.Substring(6).Split('-');
235 if (rangeValues.Length == 2)
236 {
237 if (Int32.TryParse(rangeValues[0], out start) && Int32.TryParse(rangeValues[1], out end))
238 return true;
239 }
240 }
241
242 start = end = 0;
243 return false;
244 }
115 } 245 }
116} \ No newline at end of file 246} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
index c275d87..6437d0b 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
@@ -68,7 +68,7 @@ namespace OpenSim.Capabilities.Handlers
68 ret["content_type"] = "text/plain"; 68 ret["content_type"] = "text/plain";
69 ret["keepalive"] = false; 69 ret["keepalive"] = false;
70 ret["reusecontext"] = false; 70 ret["reusecontext"] = false;
71 71 ret["int_bytes"] = 0;
72 string textureStr = (string)request["texture_id"]; 72 string textureStr = (string)request["texture_id"];
73 string format = (string)request["format"]; 73 string format = (string)request["format"];
74 74
@@ -237,6 +237,7 @@ namespace OpenSim.Capabilities.Handlers
237 { 237 {
238 response["int_response_code"] = (int)System.Net.HttpStatusCode.OK; 238 response["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
239 response["bin_response_data"] = texture.Data; 239 response["bin_response_data"] = texture.Data;
240 response["int_bytes"] = texture.Data.Length;
240 } 241 }
241 else 242 else
242 { 243 {
@@ -246,6 +247,7 @@ namespace OpenSim.Capabilities.Handlers
246 byte[] d = new byte[len]; 247 byte[] d = new byte[len];
247 Array.Copy(texture.Data, start, d, 0, len); 248 Array.Copy(texture.Data, start, d, 0, len);
248 response["bin_response_data"] = d; 249 response["bin_response_data"] = d;
250 response["int_bytes"] = len;
249 } 251 }
250// response.Body.Write(texture.Data, start, len); 252// response.Body.Write(texture.Data, start, len);
251 } 253 }
@@ -266,6 +268,8 @@ namespace OpenSim.Capabilities.Handlers
266 response["content_type"] = "image/" + format; 268 response["content_type"] = "image/" + format;
267 269
268 response["bin_response_data"] = texture.Data; 270 response["bin_response_data"] = texture.Data;
271 response["int_bytes"] = texture.Data.Length;
272
269// response.Body.Write(texture.Data, 0, texture.Data.Length); 273// response.Body.Write(texture.Data, 0, texture.Data.Length);
270 } 274 }
271 275
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index a1df637..1c6685a 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -1053,7 +1053,7 @@ namespace OpenSim.Framework
1053 event MuteListEntryRemove OnRemoveMuteListEntry; 1053 event MuteListEntryRemove OnRemoveMuteListEntry;
1054 event GodlikeMessage onGodlikeMessage; 1054 event GodlikeMessage onGodlikeMessage;
1055 event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 1055 event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
1056 1056 event GenericCall2 OnUpdateThrottles;
1057 /// <summary> 1057 /// <summary>
1058 /// Set the debug level at which packet output should be printed to console. 1058 /// Set the debug level at which packet output should be printed to console.
1059 /// </summary> 1059 /// </summary>
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
index d0a37d0..c19ac32 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
@@ -53,7 +53,8 @@ namespace OpenSim.Framework.Servers.HttpServer
53 Normal = 0, 53 Normal = 0,
54 LslHttp = 1, 54 LslHttp = 1,
55 Inventory = 2, 55 Inventory = 2,
56 Texture = 3 56 Texture = 3,
57 Mesh = 4
57 } 58 }
58 59
59 public PollServiceEventArgs( 60 public PollServiceEventArgs(
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
index 0d7b1fc..8deff81 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;
@@ -57,8 +60,42 @@ 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 struct aPollRequest
64 {
65 public PollServiceMeshEventArgs thepoll;
66 public UUID reqID;
67 public Hashtable request;
68 }
69
70 public class aPollResponse
71 {
72 public Hashtable response;
73 public int bytes;
74 }
75
76
77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
78
79 private static GetMeshHandler m_getMeshHandler;
80
81 private IAssetService m_assetService = null;
82
83 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
84 private static Thread[] m_workerThreads = null;
85
86 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
87 new OpenMetaverse.BlockingQueue<aPollRequest>();
88
89 private Dictionary<UUID, PollServiceMeshEventArgs> m_pollservices = new Dictionary<UUID, PollServiceMeshEventArgs>();
60 90
61 #region IRegionModuleBase Members 91 #region ISharedRegionModule Members
92
93 ~GetMeshModule()
94 {
95 foreach (Thread t in m_workerThreads)
96 Watchdog.AbortThread(t.ManagedThreadId);
97
98 }
62 99
63 public Type ReplaceableInterface 100 public Type ReplaceableInterface
64 { 101 {
@@ -83,6 +120,8 @@ namespace OpenSim.Region.ClientStack.Linden
83 return; 120 return;
84 121
85 m_scene = pScene; 122 m_scene = pScene;
123
124 m_assetService = pScene.AssetService;
86 } 125 }
87 126
88 public void RemoveRegion(Scene scene) 127 public void RemoveRegion(Scene scene)
@@ -91,6 +130,9 @@ namespace OpenSim.Region.ClientStack.Linden
91 return; 130 return;
92 131
93 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 132 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
133 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
134 m_scene.EventManager.OnThrottleUpdate -= ThrottleUpdate;
135
94 m_scene = null; 136 m_scene = null;
95 } 137 }
96 138
@@ -101,6 +143,27 @@ namespace OpenSim.Region.ClientStack.Linden
101 143
102 m_AssetService = m_scene.RequestModuleInterface<IAssetService>(); 144 m_AssetService = m_scene.RequestModuleInterface<IAssetService>();
103 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 145 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
146 // We'll reuse the same handler for all requests.
147 m_getMeshHandler = new GetMeshHandler(m_assetService);
148 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
149 m_scene.EventManager.OnThrottleUpdate += ThrottleUpdate;
150
151 if (m_workerThreads == null)
152 {
153 m_workerThreads = new Thread[2];
154
155 for (uint i = 0; i < 2; i++)
156 {
157 m_workerThreads[i] = Watchdog.StartThread(DoMeshRequests,
158 String.Format("MeshWorkerThread{0}", i),
159 ThreadPriority.Normal,
160 false,
161 false,
162 null,
163 int.MaxValue);
164 }
165 }
166
104 } 167 }
105 168
106 169
@@ -110,25 +173,209 @@ namespace OpenSim.Region.ClientStack.Linden
110 173
111 #endregion 174 #endregion
112 175
176 private void DoMeshRequests()
177 {
178 while (true)
179 {
180 aPollRequest poolreq = m_queue.Dequeue();
181
182 poolreq.thepoll.Process(poolreq);
183 }
184 }
185
186 // 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.
187 public void ThrottleUpdate(ScenePresence p)
188 {
189 byte[] throttles = p.ControllingClient.GetThrottlesPacked(1);
190 UUID user = p.UUID;
191 int imagethrottle = ExtractTaskThrottle(throttles);
192 PollServiceMeshEventArgs args;
193 if (m_pollservices.TryGetValue(user, out args))
194 {
195 args.UpdateThrottle(imagethrottle);
196 }
197 }
198
199 private int ExtractTaskThrottle(byte[] pthrottles)
200 {
201
202 byte[] adjData;
203 int pos = 0;
204
205 if (!BitConverter.IsLittleEndian)
206 {
207 byte[] newData = new byte[7 * 4];
208 Buffer.BlockCopy(pthrottles, 0, newData, 0, 7 * 4);
209
210 for (int i = 0; i < 7; i++)
211 Array.Reverse(newData, i * 4, 4);
212
213 adjData = newData;
214 }
215 else
216 {
217 adjData = pthrottles;
218 }
219
220 // 0.125f converts from bits to bytes
221 //int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
222 //pos += 4;
223 // int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
224 //pos += 4;
225 // int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
226 // pos += 4;
227 // int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
228 // pos += 4;
229 pos += 16;
230 int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
231 // pos += 4;
232 //int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); //pos += 4;
233 //int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
234 return task;
235 }
236
237 private class PollServiceMeshEventArgs : PollServiceEventArgs
238 {
239 private List<Hashtable> requests =
240 new List<Hashtable>();
241 private Dictionary<UUID, aPollResponse> responses =
242 new Dictionary<UUID, aPollResponse>();
243
244 private Scene m_scene;
245 private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000, 10000);
246 public PollServiceMeshEventArgs(UUID pId, Scene scene) :
247 base(null, null, null, null, pId, int.MaxValue)
248 {
249 m_scene = scene;
250 // x is request id, y is userid
251 HasEvents = (x, y) =>
252 {
253 lock (responses)
254 {
255 bool ret = m_throttler.hasEvents(x, responses);
256 m_throttler.ProcessTime();
257 return ret;
258
259 }
260 };
261 GetEvents = (x, y) =>
262 {
263 lock (responses)
264 {
265 try
266 {
267 return responses[x].response;
268 }
269 finally
270 {
271 responses.Remove(x);
272 }
273 }
274 };
275 // x is request id, y is request data hashtable
276 Request = (x, y) =>
277 {
278 aPollRequest reqinfo = new aPollRequest();
279 reqinfo.thepoll = this;
280 reqinfo.reqID = x;
281 reqinfo.request = y;
282
283 m_queue.Enqueue(reqinfo);
284 };
285
286 // this should never happen except possible on shutdown
287 NoEvents = (x, y) =>
288 {
289 /*
290 lock (requests)
291 {
292 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
293 requests.Remove(request);
294 }
295 */
296 Hashtable response = new Hashtable();
297
298 response["int_response_code"] = 500;
299 response["str_response_string"] = "Script timeout";
300 response["content_type"] = "text/plain";
301 response["keepalive"] = false;
302 response["reusecontext"] = false;
303
304 return response;
305 };
306 }
307
308 public void Process(aPollRequest requestinfo)
309 {
310 Hashtable response;
311
312 UUID requestID = requestinfo.reqID;
313
314 // If the avatar is gone, don't bother to get the texture
315 if (m_scene.GetScenePresence(Id) == null)
316 {
317 response = new Hashtable();
318
319 response["int_response_code"] = 500;
320 response["str_response_string"] = "Script timeout";
321 response["content_type"] = "text/plain";
322 response["keepalive"] = false;
323 response["reusecontext"] = false;
324
325 lock (responses)
326 responses[requestID] = new aPollResponse() { bytes = 0, response = response };
327
328 return;
329 }
330
331 response = m_getMeshHandler.Handle(requestinfo.request);
332 lock (responses)
333 {
334 responses[requestID] = new aPollResponse()
335 {
336 bytes = (int)response["int_bytes"],
337 response = response
338 };
339
340 }
341 m_throttler.ProcessTime();
342 }
343
344 internal void UpdateThrottle(int pimagethrottle)
345 {
346 m_throttler.ThrottleBytes = pimagethrottle;
347 }
348 }
113 349
114 public void RegisterCaps(UUID agentID, Caps caps) 350 public void RegisterCaps(UUID agentID, Caps caps)
115 { 351 {
116// UUID capID = UUID.Random(); 352// UUID capID = UUID.Random();
117
118 //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture));
119 if (m_URL == "localhost") 353 if (m_URL == "localhost")
120 { 354 {
121// m_log.DebugFormat("[GETMESH]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); 355 string capUrl = "/CAPS/" + UUID.Random() + "/";
122 GetMeshHandler gmeshHandler = new GetMeshHandler(m_AssetService); 356
123 IRequestHandler reqHandler 357 // Register this as a poll service
124 = new RestHTTPHandler( 358 PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(agentID, m_scene);
125 "GET", 359
126 "/CAPS/" + UUID.Random(), 360 args.Type = PollServiceEventArgs.EventType.Mesh;
127 httpMethod => gmeshHandler.ProcessGetMesh(httpMethod, UUID.Zero, null), 361 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
128 "GetMesh", 362
129 agentID.ToString()); 363 string hostName = m_scene.RegionInfo.ExternalHostName;
364 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
365 string protocol = "http";
130 366
131 caps.RegisterHandler("GetMesh", reqHandler); 367 if (MainServer.Instance.UseSSL)
368 {
369 hostName = MainServer.Instance.SSLCommonName;
370 port = MainServer.Instance.SSLPort;
371 protocol = "https";
372 }
373 caps.RegisterHandler("GetMesh", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
374 m_pollservices.Add(agentID, args);
375 m_capsDict[agentID] = capUrl;
376
377
378
132 } 379 }
133 else 380 else
134 { 381 {
@@ -136,6 +383,95 @@ namespace OpenSim.Region.ClientStack.Linden
136 caps.RegisterHandler("GetMesh", m_URL); 383 caps.RegisterHandler("GetMesh", m_URL);
137 } 384 }
138 } 385 }
386 private void DeregisterCaps(UUID agentID, Caps caps)
387 {
388 string capUrl;
389 PollServiceMeshEventArgs args;
390 if (m_capsDict.TryGetValue(agentID, out capUrl))
391 {
392 MainServer.Instance.RemoveHTTPHandler("", capUrl);
393 m_capsDict.Remove(agentID);
394 }
395 if (m_pollservices.TryGetValue(agentID, out args))
396 {
397 m_pollservices.Remove(agentID);
398 }
399 }
400
401 internal sealed class CapsDataThrottler
402 {
403
404 private volatile int currenttime = 0;
405 private volatile int lastTimeElapsed = 0;
406 private volatile int BytesSent = 0;
407 private int oversizedImages = 0;
408 public CapsDataThrottler(int pBytes, int max, int min)
409 {
410 ThrottleBytes = pBytes;
411 lastTimeElapsed = Util.EnvironmentTickCount();
412 }
413 public bool hasEvents(UUID key, Dictionary<UUID, aPollResponse> responses)
414 {
415 PassTime();
416 // Note, this is called IN LOCK
417 bool haskey = responses.ContainsKey(key);
418 if (!haskey)
419 {
420 return false;
421 }
422 aPollResponse response;
423 if (responses.TryGetValue(key, out response))
424 {
425
426 // Normal
427 if (BytesSent + response.bytes <= ThrottleBytes)
428 {
429 BytesSent += response.bytes;
430 //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + 1000, unlockyn = false };
431 //m_actions.Add(timeBasedAction);
432 return true;
433 }
434 // Big textures
435 else if (response.bytes > ThrottleBytes && oversizedImages <= ((ThrottleBytes % 50000) + 1))
436 {
437 Interlocked.Increment(ref oversizedImages);
438 BytesSent += response.bytes;
439 //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + (((response.bytes % ThrottleBytes)+1)*1000) , unlockyn = false };
440 //m_actions.Add(timeBasedAction);
441 return true;
442 }
443 else
444 {
445 return false;
446 }
447 }
448
449 return haskey;
450 }
451 public void ProcessTime()
452 {
453 PassTime();
454 }
455
456
457 private void PassTime()
458 {
459 currenttime = Util.EnvironmentTickCount();
460 int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed);
461 //processTimeBasedActions(responses);
462 if (Util.EnvironmentTickCountSubtract(currenttime, timeElapsed) >= 1000)
463 {
464 lastTimeElapsed = Util.EnvironmentTickCount();
465 BytesSent -= ThrottleBytes;
466 if (BytesSent < 0) BytesSent = 0;
467 if (BytesSent < ThrottleBytes)
468 {
469 oversizedImages = 0;
470 }
471 }
472 }
473 public int ThrottleBytes;
474 }
139 475
140 } 476 }
141} 477}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
index d1a1583..c8c709a 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
@@ -61,6 +61,13 @@ namespace OpenSim.Region.ClientStack.Linden
61 public Hashtable request; 61 public Hashtable request;
62 } 62 }
63 63
64 public class aPollResponse
65 {
66 public Hashtable response;
67 public int bytes;
68 }
69
70
64 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 71 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
65 72
66 private Scene m_scene; 73 private Scene m_scene;
@@ -75,6 +82,8 @@ namespace OpenSim.Region.ClientStack.Linden
75 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue = 82 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
76 new OpenMetaverse.BlockingQueue<aPollRequest>(); 83 new OpenMetaverse.BlockingQueue<aPollRequest>();
77 84
85 private Dictionary<UUID,PollServiceTextureEventArgs> m_pollservices = new Dictionary<UUID,PollServiceTextureEventArgs>();
86
78 #region ISharedRegionModule Members 87 #region ISharedRegionModule Members
79 88
80 public void Initialise(IConfigSource source) 89 public void Initialise(IConfigSource source)
@@ -91,6 +100,7 @@ namespace OpenSim.Region.ClientStack.Linden
91 { 100 {
92 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 101 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
93 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps; 102 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
103 m_scene.EventManager.OnThrottleUpdate -= ThrottleUpdate;
94 m_scene = null; 104 m_scene = null;
95 } 105 }
96 106
@@ -101,6 +111,7 @@ namespace OpenSim.Region.ClientStack.Linden
101 111
102 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 112 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
103 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps; 113 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
114 m_scene.EventManager.OnThrottleUpdate += ThrottleUpdate;
104 115
105 if (m_workerThreads == null) 116 if (m_workerThreads == null)
106 { 117 {
@@ -118,6 +129,56 @@ namespace OpenSim.Region.ClientStack.Linden
118 } 129 }
119 } 130 }
120 } 131 }
132 private int ExtractImageThrottle(byte[] pthrottles)
133 {
134
135 byte[] adjData;
136 int pos = 0;
137
138 if (!BitConverter.IsLittleEndian)
139 {
140 byte[] newData = new byte[7 * 4];
141 Buffer.BlockCopy(pthrottles, 0, newData, 0, 7 * 4);
142
143 for (int i = 0; i < 7; i++)
144 Array.Reverse(newData, i * 4, 4);
145
146 adjData = newData;
147 }
148 else
149 {
150 adjData = pthrottles;
151 }
152
153 // 0.125f converts from bits to bytes
154 //int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
155 //pos += 4;
156 // int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
157 //pos += 4;
158 // int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
159 // pos += 4;
160 // int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
161 // pos += 4;
162 // int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
163 // pos += 4;
164 pos = pos + 20;
165 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); //pos += 4;
166 //int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
167 return texture;
168 }
169
170 // 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.
171 public void ThrottleUpdate(ScenePresence p)
172 {
173 byte[] throttles = p.ControllingClient.GetThrottlesPacked(1);
174 UUID user = p.UUID;
175 int imagethrottle = ExtractImageThrottle(throttles);
176 PollServiceTextureEventArgs args;
177 if (m_pollservices.TryGetValue(user,out args))
178 {
179 args.UpdateThrottle(imagethrottle);
180 }
181 }
121 182
122 public void PostInitialise() 183 public void PostInitialise()
123 { 184 {
@@ -145,20 +206,25 @@ namespace OpenSim.Region.ClientStack.Linden
145 { 206 {
146 private List<Hashtable> requests = 207 private List<Hashtable> requests =
147 new List<Hashtable>(); 208 new List<Hashtable>();
148 private Dictionary<UUID, Hashtable> responses = 209 private Dictionary<UUID, aPollResponse> responses =
149 new Dictionary<UUID, Hashtable>(); 210 new Dictionary<UUID, aPollResponse>();
150 211
151 private Scene m_scene; 212 private Scene m_scene;
152 213 private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000);
153 public PollServiceTextureEventArgs(UUID pId, Scene scene) : 214 public PollServiceTextureEventArgs(UUID pId, Scene scene) :
154 base(null, null, null, null, pId, int.MaxValue) 215 base(null, null, null, null, pId, int.MaxValue)
155 { 216 {
156 m_scene = scene; 217 m_scene = scene;
157 218 // x is request id, y is userid
158 HasEvents = (x, y) => 219 HasEvents = (x, y) =>
159 { 220 {
160 lock (responses) 221 lock (responses)
161 return responses.ContainsKey(x); 222 {
223 bool ret = m_throttler.hasEvents(x, responses);
224 m_throttler.ProcessTime();
225 return ret;
226
227 }
162 }; 228 };
163 GetEvents = (x, y) => 229 GetEvents = (x, y) =>
164 { 230 {
@@ -166,7 +232,7 @@ namespace OpenSim.Region.ClientStack.Linden
166 { 232 {
167 try 233 try
168 { 234 {
169 return responses[x]; 235 return responses[x].response;
170 } 236 }
171 finally 237 finally
172 { 238 {
@@ -174,14 +240,14 @@ namespace OpenSim.Region.ClientStack.Linden
174 } 240 }
175 } 241 }
176 }; 242 };
177 243 // x is request id, y is request data hashtable
178 Request = (x, y) => 244 Request = (x, y) =>
179 { 245 {
180 aPollRequest reqinfo = new aPollRequest(); 246 aPollRequest reqinfo = new aPollRequest();
181 reqinfo.thepoll = this; 247 reqinfo.thepoll = this;
182 reqinfo.reqID = x; 248 reqinfo.reqID = x;
183 reqinfo.request = y; 249 reqinfo.request = y;
184 250
185 m_queue.Enqueue(reqinfo); 251 m_queue.Enqueue(reqinfo);
186 }; 252 };
187 253
@@ -223,16 +289,29 @@ namespace OpenSim.Region.ClientStack.Linden
223 response["content_type"] = "text/plain"; 289 response["content_type"] = "text/plain";
224 response["keepalive"] = false; 290 response["keepalive"] = false;
225 response["reusecontext"] = false; 291 response["reusecontext"] = false;
226 292
227 lock (responses) 293 lock (responses)
228 responses[requestID] = response; 294 responses[requestID] = new aPollResponse() {bytes = 0, response = response};
229 295
230 return; 296 return;
231 } 297 }
232 298
233 response = m_getTextureHandler.Handle(requestinfo.request); 299 response = m_getTextureHandler.Handle(requestinfo.request);
234 lock (responses) 300 lock (responses)
235 responses[requestID] = response; 301 {
302 responses[requestID] = new aPollResponse()
303 {
304 bytes = (int) response["int_bytes"],
305 response = response
306 };
307
308 }
309 m_throttler.ProcessTime();
310 }
311
312 internal void UpdateThrottle(int pimagethrottle)
313 {
314 m_throttler.ThrottleBytes = pimagethrottle;
236 } 315 }
237 } 316 }
238 317
@@ -257,19 +336,23 @@ namespace OpenSim.Region.ClientStack.Linden
257 protocol = "https"; 336 protocol = "https";
258 } 337 }
259 caps.RegisterHandler("GetTexture", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl)); 338 caps.RegisterHandler("GetTexture", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
260 339 m_pollservices.Add(agentID, args);
261 m_capsDict[agentID] = capUrl; 340 m_capsDict[agentID] = capUrl;
262 } 341 }
263 342
264 private void DeregisterCaps(UUID agentID, Caps caps) 343 private void DeregisterCaps(UUID agentID, Caps caps)
265 { 344 {
266 string capUrl; 345 string capUrl;
267 346 PollServiceTextureEventArgs args;
268 if (m_capsDict.TryGetValue(agentID, out capUrl)) 347 if (m_capsDict.TryGetValue(agentID, out capUrl))
269 { 348 {
270 MainServer.Instance.RemoveHTTPHandler("", capUrl); 349 MainServer.Instance.RemoveHTTPHandler("", capUrl);
271 m_capsDict.Remove(agentID); 350 m_capsDict.Remove(agentID);
272 } 351 }
352 if (m_pollservices.TryGetValue(agentID, out args))
353 {
354 m_pollservices.Remove(agentID);
355 }
273 } 356 }
274 357
275 private void DoTextureRequests() 358 private void DoTextureRequests()
@@ -281,5 +364,81 @@ namespace OpenSim.Region.ClientStack.Linden
281 poolreq.thepoll.Process(poolreq); 364 poolreq.thepoll.Process(poolreq);
282 } 365 }
283 } 366 }
367 internal sealed class CapsDataThrottler
368 {
369
370 private volatile int currenttime = 0;
371 private volatile int lastTimeElapsed = 0;
372 private volatile int BytesSent = 0;
373 private int oversizedImages = 0;
374 public CapsDataThrottler(int pBytes, int max, int min)
375 {
376 ThrottleBytes = pBytes;
377 lastTimeElapsed = Util.EnvironmentTickCount();
378 }
379 public bool hasEvents(UUID key, Dictionary<UUID, GetTextureModule.aPollResponse> responses)
380 {
381 PassTime();
382 // Note, this is called IN LOCK
383 bool haskey = responses.ContainsKey(key);
384 if (!haskey)
385 {
386 return false;
387 }
388 GetTextureModule.aPollResponse response;
389 if (responses.TryGetValue(key, out response))
390 {
391
392 // Normal
393 if (BytesSent + response.bytes <= ThrottleBytes)
394 {
395 BytesSent += response.bytes;
396 //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + 1000, unlockyn = false };
397 //m_actions.Add(timeBasedAction);
398 return true;
399 }
400 // Big textures
401 else if (response.bytes > ThrottleBytes && oversizedImages <= ((ThrottleBytes % 50000) + 1))
402 {
403 Interlocked.Increment(ref oversizedImages);
404 BytesSent += response.bytes;
405 //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + (((response.bytes % ThrottleBytes)+1)*1000) , unlockyn = false };
406 //m_actions.Add(timeBasedAction);
407 return true;
408 }
409 else
410 {
411 return false;
412 }
413 }
414
415 return haskey;
416 }
417 public void ProcessTime()
418 {
419 PassTime();
420 }
421
422
423 private void PassTime()
424 {
425 currenttime = Util.EnvironmentTickCount();
426 int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed);
427 //processTimeBasedActions(responses);
428 if (Util.EnvironmentTickCountSubtract(currenttime, timeElapsed) >= 1000)
429 {
430 lastTimeElapsed = Util.EnvironmentTickCount();
431 BytesSent -= ThrottleBytes;
432 if (BytesSent < 0) BytesSent = 0;
433 if (BytesSent < ThrottleBytes)
434 {
435 oversizedImages = 0;
436 }
437 }
438 }
439 public int ThrottleBytes;
440 }
284 } 441 }
442
443
285} 444}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 1f6af4a..c9aa4ca 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -296,6 +296,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
296 public event MuteListEntryRemove OnRemoveMuteListEntry; 296 public event MuteListEntryRemove OnRemoveMuteListEntry;
297 public event GodlikeMessage onGodlikeMessage; 297 public event GodlikeMessage onGodlikeMessage;
298 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 298 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
299 public event GenericCall2 OnUpdateThrottles;
299 300
300 #endregion Events 301 #endregion Events
301 302
@@ -6753,6 +6754,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6753 #endregion 6754 #endregion
6754 6755
6755 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 }
6756 return true; 6762 return true;
6757 } 6763 }
6758 6764
@@ -11906,6 +11912,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11906 public void SetChildAgentThrottle(byte[] throttles) 11912 public void SetChildAgentThrottle(byte[] throttles)
11907 { 11913 {
11908 m_udpClient.SetThrottles(throttles); 11914 m_udpClient.SetThrottles(throttles);
11915 GenericCall2 handler = OnUpdateThrottles;
11916 if (handler != null)
11917 {
11918 handler();
11919 }
11909 } 11920 }
11910 11921
11911 /// <summary> 11922 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 8691b91..5b1c9f4 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -816,6 +816,10 @@ namespace OpenSim.Region.Framework.Scenes
816 public event ParcelPrimCountTainted OnParcelPrimCountTainted; 816 public event ParcelPrimCountTainted OnParcelPrimCountTainted;
817 public event GetScriptRunning OnGetScriptRunning; 817 public event GetScriptRunning OnGetScriptRunning;
818 818
819 public delegate void ThrottleUpdate(ScenePresence scenePresence);
820
821 public event ThrottleUpdate OnThrottleUpdate;
822
819 /// <summary> 823 /// <summary>
820 /// RegisterCapsEvent is called by Scene after the Caps object 824 /// RegisterCapsEvent is called by Scene after the Caps object
821 /// has been instantiated and before it is return to the 825 /// has been instantiated and before it is return to the
@@ -3130,5 +3134,14 @@ namespace OpenSim.Region.Framework.Scenes
3130 } 3134 }
3131 } 3135 }
3132 } 3136 }
3137
3138 public void TriggerThrottleUpdate(ScenePresence scenePresence)
3139 {
3140 ThrottleUpdate handler = OnThrottleUpdate;
3141 if (handler != null)
3142 {
3143 handler(scenePresence);
3144 }
3145 }
3133 } 3146 }
3134} 3147}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 2c18397..25a53b4 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -794,6 +794,7 @@ namespace OpenSim.Region.Framework.Scenes
794 ControllingClient.OnChangeAnim += avnHandleChangeAnim; 794 ControllingClient.OnChangeAnim += avnHandleChangeAnim;
795 ControllingClient.OnForceReleaseControls += HandleForceReleaseControls; 795 ControllingClient.OnForceReleaseControls += HandleForceReleaseControls;
796 ControllingClient.OnAutoPilotGo += MoveToTarget; 796 ControllingClient.OnAutoPilotGo += MoveToTarget;
797 ControllingClient.OnUpdateThrottles += RaiseUpdateThrottles;
797 798
798 // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); 799 // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange);
799 // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); 800 // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement);
@@ -3174,6 +3175,10 @@ namespace OpenSim.Region.Framework.Scenes
3174 } 3175 }
3175 3176
3176 private static Vector3 marker = new Vector3(-1f, -1f, -1f); 3177 private static Vector3 marker = new Vector3(-1f, -1f, -1f);
3178 private void RaiseUpdateThrottles()
3179 {
3180 m_scene.EventManager.TriggerThrottleUpdate(this);
3181 }
3177 /// <summary> 3182 /// <summary>
3178 /// This updates important decision making data about a child agent 3183 /// This updates important decision making data about a child agent
3179 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region 3184 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index c363fd3..254eeb4 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -873,6 +873,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
873 public event MuteListEntryRemove OnRemoveMuteListEntry; 873 public event MuteListEntryRemove OnRemoveMuteListEntry;
874 public event GodlikeMessage onGodlikeMessage; 874 public event GodlikeMessage onGodlikeMessage;
875 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 875 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
876 public event GenericCall2 OnUpdateThrottles;
876 877
877#pragma warning restore 67 878#pragma warning restore 67
878 879
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 5471afa..3a03101 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -473,7 +473,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
473 public event MuteListEntryRemove OnRemoveMuteListEntry; 473 public event MuteListEntryRemove OnRemoveMuteListEntry;
474 public event GodlikeMessage onGodlikeMessage; 474 public event GodlikeMessage onGodlikeMessage;
475 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 475 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
476 476 public event GenericCall2 OnUpdateThrottles;
477#pragma warning restore 67 477#pragma warning restore 67
478 478
479 #endregion 479 #endregion
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index ebdfb4f..5ad3c9f 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -320,7 +320,7 @@ namespace OpenSim.Tests.Common.Mock
320 public event MuteListEntryRemove OnRemoveMuteListEntry; 320 public event MuteListEntryRemove OnRemoveMuteListEntry;
321 public event GodlikeMessage onGodlikeMessage; 321 public event GodlikeMessage onGodlikeMessage;
322 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 322 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
323 323 public event GenericCall2 OnUpdateThrottles;
324#pragma warning restore 67 324#pragma warning restore 67
325 325
326 /// <value> 326 /// <value>