aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs406
1 files changed, 0 insertions, 406 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
deleted file mode 100644
index 87e23de..0000000
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
+++ /dev/null
@@ -1,406 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Collections.Concurrent;
32using System.Reflection;
33using System.Threading;
34using log4net;
35using Nini.Config;
36using Mono.Addins;
37using OpenMetaverse;
38using OpenSim.Framework;
39using OpenSim.Framework.Servers;
40using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Services.Interfaces;
44using Caps = OpenSim.Framework.Capabilities.Caps;
45using OpenSim.Capabilities.Handlers;
46using OpenSim.Framework.Monitoring;
47
48namespace OpenSim.Region.ClientStack.Linden
49{
50
51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetTextureModule")]
52 public class GetTextureModule : INonSharedRegionModule
53 {
54
55 class APollRequest
56 {
57 public PollServiceTextureEventArgs thepoll;
58 public UUID reqID;
59 public Hashtable request;
60 public bool send503;
61 }
62
63 public class APollResponse
64 {
65 public Hashtable response;
66 public int bytes;
67 }
68
69
70 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
71
72 private Scene m_scene;
73
74 private static GetTextureHandler m_getTextureHandler;
75
76 private IAssetService m_assetService = null;
77
78 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
79 private static Thread[] m_workerThreads = null;
80 private static int m_NumberScenes = 0;
81 private static BlockingCollection<APollRequest> m_queue = new BlockingCollection<APollRequest>();
82
83 private Dictionary<UUID,PollServiceTextureEventArgs> m_pollservices = new Dictionary<UUID,PollServiceTextureEventArgs>();
84
85 private string m_Url = "localhost";
86
87 #region ISharedRegionModule Members
88
89 public void Initialise(IConfigSource source)
90 {
91 IConfig config = source.Configs["ClientStack.LindenCaps"];
92
93 if (config == null)
94 return;
95/*
96 m_URL = config.GetString("Cap_GetTexture", string.Empty);
97 // Cap doesn't exist
98 if (m_URL != string.Empty)
99 {
100 m_Enabled = true;
101 m_RedirectURL = config.GetString("GetTextureRedirectURL");
102 }
103*/
104 m_Url = config.GetString("Cap_GetTexture", "localhost");
105 }
106
107 public void AddRegion(Scene s)
108 {
109 m_scene = s;
110 }
111
112 public void RemoveRegion(Scene s)
113 {
114 s.EventManager.OnRegisterCaps -= RegisterCaps;
115 s.EventManager.OnDeregisterCaps -= DeregisterCaps;
116 m_NumberScenes--;
117 m_scene = null;
118 }
119
120 public void RegionLoaded(Scene s)
121 {
122 if(m_assetService == null)
123 {
124 m_assetService = s.RequestModuleInterface<IAssetService>();
125 // We'll reuse the same handler for all requests.
126 m_getTextureHandler = new GetTextureHandler(m_assetService);
127 }
128
129 s.EventManager.OnRegisterCaps += RegisterCaps;
130 s.EventManager.OnDeregisterCaps += DeregisterCaps;
131
132 m_NumberScenes++;
133
134 if (m_workerThreads == null)
135 {
136 m_workerThreads = new Thread[2];
137
138 for (uint i = 0; i < 2; i++)
139 {
140 m_workerThreads[i] = WorkManager.StartThread(DoTextureRequests,
141 String.Format("GetTextureWorker{0}", i),
142 ThreadPriority.Normal,
143 true,
144 false,
145 null,
146 int.MaxValue);
147 }
148 }
149 }
150
151 public void PostInitialise()
152 {
153 }
154
155 public void Close()
156 {
157 if(m_NumberScenes <= 0 && m_workerThreads != null)
158 {
159 m_log.DebugFormat("[GetTextureModule] Closing");
160
161 foreach (Thread t in m_workerThreads)
162 Watchdog.AbortThread(t.ManagedThreadId);
163
164 m_queue.Dispose();
165 }
166 }
167
168 public string Name { get { return "GetTextureModule"; } }
169
170 public Type ReplaceableInterface
171 {
172 get { return null; }
173 }
174
175 #endregion
176
177 private class PollServiceTextureEventArgs : PollServiceEventArgs
178 {
179 private List<Hashtable> requests =
180 new List<Hashtable>();
181 private Dictionary<UUID, APollResponse> responses =
182 new Dictionary<UUID, APollResponse>();
183 private HashSet<UUID> dropedResponses = new HashSet<UUID>();
184
185 private Scene m_scene;
186 private ScenePresence m_presence;
187 public PollServiceTextureEventArgs(UUID pId, Scene scene) :
188 base(null, "", null, null, null, null, pId, int.MaxValue)
189 {
190 m_scene = scene;
191 // x is request id, y is userid
192 HasEvents = (x, y) =>
193 {
194 lock (responses)
195 {
196 APollResponse response;
197 if (responses.TryGetValue(x, out response))
198 {
199 if (m_presence == null)
200 m_presence = m_scene.GetScenePresence(pId);
201
202 if (m_presence == null || m_presence.IsDeleted)
203 return true;
204 return m_presence.CapCanSendAsset(0, response.bytes);
205 }
206 return false;
207 }
208 };
209
210 Drop = (x, y) =>
211 {
212 lock (responses)
213 {
214 responses.Remove(x);
215 dropedResponses.Add(x);
216 }
217 };
218
219 GetEvents = (x, y) =>
220 {
221 lock (responses)
222 {
223 try
224 {
225 return responses[x].response;
226 }
227 finally
228 {
229 responses.Remove(x);
230 }
231 }
232 };
233 // x is request id, y is request data hashtable
234 Request = (x, y) =>
235 {
236 APollRequest reqinfo = new APollRequest();
237 reqinfo.thepoll = this;
238 reqinfo.reqID = x;
239 reqinfo.request = y;
240 reqinfo.send503 = false;
241
242 lock (responses)
243 {
244 if (responses.Count > 0 && m_queue.Count > 32)
245 reqinfo.send503 = true;
246 }
247
248 m_queue.Add(reqinfo);
249 };
250
251 // this should never happen except possible on shutdown
252 NoEvents = (x, y) =>
253 {
254/*
255 lock (requests)
256 {
257 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
258 requests.Remove(request);
259 }
260*/
261 Hashtable response = new Hashtable();
262
263 response["int_response_code"] = 500;
264 response["str_response_string"] = "timeout";
265 response["content_type"] = "text/plain";
266 response["keepalive"] = false;
267 return response;
268 };
269 }
270
271 public void Process(APollRequest requestinfo)
272 {
273 Hashtable response;
274
275 UUID requestID = requestinfo.reqID;
276
277 if(m_scene.ShuttingDown)
278 return;
279
280 lock (responses)
281 {
282 lock(dropedResponses)
283 {
284 if(dropedResponses.Contains(requestID))
285 {
286 dropedResponses.Remove(requestID);
287 return;
288 }
289 }
290
291 if (m_presence == null)
292 m_presence = m_scene.GetScenePresence(Id);
293
294 if (m_presence == null || m_presence.IsDeleted)
295 requestinfo.send503 = true;
296
297 if (requestinfo.send503)
298 {
299 response = new Hashtable();
300
301 response["int_response_code"] = 503;
302 response["str_response_string"] = "Throttled";
303 response["content_type"] = "text/plain";
304 response["keepalive"] = false;
305
306 Hashtable headers = new Hashtable();
307 headers["Retry-After"] = 20;
308 response["headers"] = headers;
309
310 responses[requestID] = new APollResponse() { bytes = 0, response = response };
311 return;
312 }
313 }
314
315 response = m_getTextureHandler.Handle(requestinfo.request);
316
317 lock (responses)
318 {
319 lock(dropedResponses)
320 {
321 if(dropedResponses.Contains(requestID))
322 {
323 dropedResponses.Remove(requestID);
324 return;
325 }
326 }
327 responses[requestID] = new APollResponse()
328 {
329 bytes = (int) response["int_bytes"],
330 response = response
331 };
332 }
333 }
334 }
335
336 private void RegisterCaps(UUID agentID, Caps caps)
337 {
338 if (m_Url == "localhost")
339 {
340 string capUrl = "/CAPS/" + UUID.Random() + "/";
341
342 // Register this as a poll service
343 PollServiceTextureEventArgs args = new PollServiceTextureEventArgs(agentID, m_scene);
344
345 args.Type = PollServiceEventArgs.EventType.Texture;
346 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
347
348 string hostName = m_scene.RegionInfo.ExternalHostName;
349 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
350 string protocol = "http";
351
352 if (MainServer.Instance.UseSSL)
353 {
354 hostName = MainServer.Instance.SSLCommonName;
355 port = MainServer.Instance.SSLPort;
356 protocol = "https";
357 }
358 IExternalCapsModule handler = m_scene.RequestModuleInterface<IExternalCapsModule>();
359 if (handler != null)
360 handler.RegisterExternalUserCapsHandler(agentID, caps, "GetTexture", capUrl);
361 else
362 caps.RegisterHandler("GetTexture", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
363 m_pollservices[agentID] = args;
364 m_capsDict[agentID] = capUrl;
365 }
366 else
367 {
368 caps.RegisterHandler("GetTexture", m_Url);
369 }
370 }
371
372 private void DeregisterCaps(UUID agentID, Caps caps)
373 {
374 PollServiceTextureEventArgs args;
375
376 MainServer.Instance.RemoveHTTPHandler("", m_Url);
377 m_capsDict.Remove(agentID);
378
379 if (m_pollservices.TryGetValue(agentID, out args))
380 {
381 m_pollservices.Remove(agentID);
382 }
383 }
384
385 private static void DoTextureRequests()
386 {
387 APollRequest poolreq;
388 while (m_NumberScenes > 0)
389 {
390 poolreq = null;
391 if(!m_queue.TryTake(out poolreq, 4500) || poolreq == null)
392 {
393 Watchdog.UpdateThread();
394 continue;
395 }
396
397 if(m_NumberScenes <= 0)
398 break;
399
400 Watchdog.UpdateThread();
401 if(poolreq.reqID != UUID.Zero)
402 poolreq.thepoll.Process(poolreq);
403 }
404 }
405 }
406}