aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
diff options
context:
space:
mode:
authorMelanie2012-11-17 02:58:14 +0000
committerMelanie2012-11-17 02:58:14 +0000
commit7ad082f7c39ba82adeae3c25ca0befcf983c879d (patch)
tree0e3c488c65ef22b53e4536dd07f46c1467b58f78 /OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
parentMerge branch 'master' into careminster (diff)
parentPrevent a buffer overflow in asset receiving (diff)
downloadopensim-SC_OLD-7ad082f7c39ba82adeae3c25ca0befcf983c879d.zip
opensim-SC_OLD-7ad082f7c39ba82adeae3c25ca0befcf983c879d.tar.gz
opensim-SC_OLD-7ad082f7c39ba82adeae3c25ca0befcf983c879d.tar.bz2
opensim-SC_OLD-7ad082f7c39ba82adeae3c25ca0befcf983c879d.tar.xz
Merge branch 'avination' into careminster
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs186
1 files changed, 172 insertions, 14 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
index 24a0190..d1ec4aa 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
@@ -58,6 +58,13 @@ namespace OpenSim.Region.ClientStack.Linden
58 public Hashtable request; 58 public Hashtable request;
59 } 59 }
60 60
61 public class aPollResponse
62 {
63 public Hashtable response;
64 public int bytes;
65 }
66
67
61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 68 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
62 69
63 private Scene m_scene; 70 private Scene m_scene;
@@ -72,6 +79,8 @@ namespace OpenSim.Region.ClientStack.Linden
72 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue = 79 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
73 new OpenMetaverse.BlockingQueue<aPollRequest>(); 80 new OpenMetaverse.BlockingQueue<aPollRequest>();
74 81
82 private Dictionary<UUID,PollServiceTextureEventArgs> m_pollservices = new Dictionary<UUID,PollServiceTextureEventArgs>();
83
75 #region ISharedRegionModule Members 84 #region ISharedRegionModule Members
76 85
77 public void Initialise(IConfigSource source) 86 public void Initialise(IConfigSource source)
@@ -88,6 +97,7 @@ namespace OpenSim.Region.ClientStack.Linden
88 { 97 {
89 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 98 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
90 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps; 99 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
100 m_scene.EventManager.OnThrottleUpdate -= ThrottleUpdate;
91 m_scene = null; 101 m_scene = null;
92 } 102 }
93 103
@@ -98,6 +108,7 @@ namespace OpenSim.Region.ClientStack.Linden
98 108
99 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 109 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
100 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps; 110 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
111 m_scene.EventManager.OnThrottleUpdate += ThrottleUpdate;
101 112
102 if (m_workerThreads == null) 113 if (m_workerThreads == null)
103 { 114 {
@@ -115,6 +126,56 @@ namespace OpenSim.Region.ClientStack.Linden
115 } 126 }
116 } 127 }
117 } 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 }
118 179
119 public void PostInitialise() 180 public void PostInitialise()
120 { 181 {
@@ -142,20 +203,25 @@ namespace OpenSim.Region.ClientStack.Linden
142 { 203 {
143 private List<Hashtable> requests = 204 private List<Hashtable> requests =
144 new List<Hashtable>(); 205 new List<Hashtable>();
145 private Dictionary<UUID, Hashtable> responses = 206 private Dictionary<UUID, aPollResponse> responses =
146 new Dictionary<UUID, Hashtable>(); 207 new Dictionary<UUID, aPollResponse>();
147 208
148 private Scene m_scene; 209 private Scene m_scene;
149 210 private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000);
150 public PollServiceTextureEventArgs(UUID pId, Scene scene) : 211 public PollServiceTextureEventArgs(UUID pId, Scene scene) :
151 base(null, null, null, null, pId, int.MaxValue) 212 base(null, null, null, null, pId, int.MaxValue)
152 { 213 {
153 m_scene = scene; 214 m_scene = scene;
154 215 // x is request id, y is userid
155 HasEvents = (x, y) => 216 HasEvents = (x, y) =>
156 { 217 {
157 lock (responses) 218 lock (responses)
158 return responses.ContainsKey(x); 219 {
220 bool ret = m_throttler.hasEvents(x, responses);
221 m_throttler.ProcessTime();
222 return ret;
223
224 }
159 }; 225 };
160 GetEvents = (x, y) => 226 GetEvents = (x, y) =>
161 { 227 {
@@ -163,7 +229,7 @@ namespace OpenSim.Region.ClientStack.Linden
163 { 229 {
164 try 230 try
165 { 231 {
166 return responses[x]; 232 return responses[x].response;
167 } 233 }
168 finally 234 finally
169 { 235 {
@@ -171,14 +237,14 @@ namespace OpenSim.Region.ClientStack.Linden
171 } 237 }
172 } 238 }
173 }; 239 };
174 240 // x is request id, y is request data hashtable
175 Request = (x, y) => 241 Request = (x, y) =>
176 { 242 {
177 aPollRequest reqinfo = new aPollRequest(); 243 aPollRequest reqinfo = new aPollRequest();
178 reqinfo.thepoll = this; 244 reqinfo.thepoll = this;
179 reqinfo.reqID = x; 245 reqinfo.reqID = x;
180 reqinfo.request = y; 246 reqinfo.request = y;
181 247
182 m_queue.Enqueue(reqinfo); 248 m_queue.Enqueue(reqinfo);
183 }; 249 };
184 250
@@ -220,16 +286,29 @@ namespace OpenSim.Region.ClientStack.Linden
220 response["content_type"] = "text/plain"; 286 response["content_type"] = "text/plain";
221 response["keepalive"] = false; 287 response["keepalive"] = false;
222 response["reusecontext"] = false; 288 response["reusecontext"] = false;
223 289
224 lock (responses) 290 lock (responses)
225 responses[requestID] = response; 291 responses[requestID] = new aPollResponse() {bytes = 0, response = response};
226 292
227 return; 293 return;
228 } 294 }
229 295
230 response = m_getTextureHandler.Handle(requestinfo.request); 296 response = m_getTextureHandler.Handle(requestinfo.request);
231 lock (responses) 297 lock (responses)
232 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;
233 } 312 }
234 } 313 }
235 314
@@ -254,19 +333,23 @@ namespace OpenSim.Region.ClientStack.Linden
254 protocol = "https"; 333 protocol = "https";
255 } 334 }
256 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));
257 336 m_pollservices.Add(agentID, args);
258 m_capsDict[agentID] = capUrl; 337 m_capsDict[agentID] = capUrl;
259 } 338 }
260 339
261 private void DeregisterCaps(UUID agentID, Caps caps) 340 private void DeregisterCaps(UUID agentID, Caps caps)
262 { 341 {
263 string capUrl; 342 string capUrl;
264 343 PollServiceTextureEventArgs args;
265 if (m_capsDict.TryGetValue(agentID, out capUrl)) 344 if (m_capsDict.TryGetValue(agentID, out capUrl))
266 { 345 {
267 MainServer.Instance.RemoveHTTPHandler("", capUrl); 346 MainServer.Instance.RemoveHTTPHandler("", capUrl);
268 m_capsDict.Remove(agentID); 347 m_capsDict.Remove(agentID);
269 } 348 }
349 if (m_pollservices.TryGetValue(agentID, out args))
350 {
351 m_pollservices.Remove(agentID);
352 }
270 } 353 }
271 354
272 private void DoTextureRequests() 355 private void DoTextureRequests()
@@ -279,4 +362,79 @@ namespace OpenSim.Region.ClientStack.Linden
279 } 362 }
280 } 363 }
281 } 364 }
365
366 internal sealed class CapsDataThrottler
367 {
368
369 private volatile int currenttime = 0;
370 private volatile int lastTimeElapsed = 0;
371 private volatile int BytesSent = 0;
372 private int oversizedImages = 0;
373 public CapsDataThrottler(int pBytes, int max, int min)
374 {
375 ThrottleBytes = pBytes;
376 lastTimeElapsed = Util.EnvironmentTickCount();
377 }
378 public bool hasEvents(UUID key, Dictionary<UUID, GetTextureModule.aPollResponse> responses)
379 {
380 PassTime();
381 // Note, this is called IN LOCK
382 bool haskey = responses.ContainsKey(key);
383 if (!haskey)
384 {
385 return false;
386 }
387 GetTextureModule.aPollResponse response;
388 if (responses.TryGetValue(key,out response))
389 {
390
391 // Normal
392 if (BytesSent + response.bytes <= ThrottleBytes)
393 {
394 BytesSent += response.bytes;
395 //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + 1000, unlockyn = false };
396 //m_actions.Add(timeBasedAction);
397 return true;
398 }
399 // Big textures
400 else if (response.bytes > ThrottleBytes && oversizedImages <= ((ThrottleBytes%50000) + 1))
401 {
402 Interlocked.Increment(ref oversizedImages);
403 BytesSent += response.bytes;
404 //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + (((response.bytes % ThrottleBytes)+1)*1000) , unlockyn = false };
405 //m_actions.Add(timeBasedAction);
406 return true;
407 }
408 else
409 {
410 return false;
411 }
412 }
413
414 return haskey;
415 }
416 public void ProcessTime()
417 {
418 PassTime();
419 }
420
421
422 private void PassTime()
423 {
424 currenttime = Util.EnvironmentTickCount();
425 int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed);
426 //processTimeBasedActions(responses);
427 if (Util.EnvironmentTickCountSubtract(currenttime, timeElapsed) >= 1000)
428 {
429 lastTimeElapsed = Util.EnvironmentTickCount();
430 BytesSent -= ThrottleBytes;
431 if (BytesSent < 0) BytesSent = 0;
432 if (BytesSent < ThrottleBytes)
433 {
434 oversizedImages = 0;
435 }
436 }
437 }
438 public int ThrottleBytes;
439 }
282} 440}