diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs | 228 |
1 files changed, 184 insertions, 44 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs index 5ae9cc3..cc65981 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs | |||
@@ -27,18 +27,13 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections; | 29 | using System.Collections; |
30 | using System.Collections.Specialized; | 30 | using System.Collections.Generic; |
31 | using System.Drawing; | ||
32 | using System.Drawing.Imaging; | ||
33 | using System.Reflection; | 31 | using System.Reflection; |
34 | using System.IO; | 32 | using System.Threading; |
35 | using System.Web; | ||
36 | using log4net; | 33 | using log4net; |
37 | using Nini.Config; | 34 | using Nini.Config; |
38 | using Mono.Addins; | 35 | using Mono.Addins; |
39 | using OpenMetaverse; | 36 | using OpenMetaverse; |
40 | using OpenMetaverse.StructuredData; | ||
41 | using OpenMetaverse.Imaging; | ||
42 | using OpenSim.Framework; | 37 | using OpenSim.Framework; |
43 | using OpenSim.Framework.Servers; | 38 | using OpenSim.Framework.Servers; |
44 | using OpenSim.Framework.Servers.HttpServer; | 39 | using OpenSim.Framework.Servers.HttpServer; |
@@ -47,64 +42,81 @@ using OpenSim.Region.Framework.Scenes; | |||
47 | using OpenSim.Services.Interfaces; | 42 | using OpenSim.Services.Interfaces; |
48 | using Caps = OpenSim.Framework.Capabilities.Caps; | 43 | using Caps = OpenSim.Framework.Capabilities.Caps; |
49 | using OpenSim.Capabilities.Handlers; | 44 | using OpenSim.Capabilities.Handlers; |
45 | using OpenSim.Framework.Monitoring; | ||
50 | 46 | ||
51 | namespace OpenSim.Region.ClientStack.Linden | 47 | namespace OpenSim.Region.ClientStack.Linden |
52 | { | 48 | { |
53 | 49 | ||
54 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] | 50 | /// <summary> |
51 | /// This module implements both WebFetchTextureDescendents and FetchTextureDescendents2 capabilities. | ||
52 | /// </summary> | ||
53 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetTextureModule")] | ||
55 | public class GetTextureModule : INonSharedRegionModule | 54 | public class GetTextureModule : INonSharedRegionModule |
56 | { | 55 | { |
57 | // private static readonly ILog m_log = | 56 | |
58 | // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 57 | struct aPollRequest |
59 | 58 | { | |
59 | public PollServiceTextureEventArgs thepoll; | ||
60 | public UUID reqID; | ||
61 | public Hashtable request; | ||
62 | } | ||
63 | |||
64 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
65 | |||
60 | private Scene m_scene; | 66 | private Scene m_scene; |
61 | private IAssetService m_assetService; | ||
62 | 67 | ||
63 | private bool m_Enabled = false; | 68 | private static GetTextureHandler m_getTextureHandler; |
69 | |||
70 | private IAssetService m_assetService = null; | ||
64 | 71 | ||
65 | // TODO: Change this to a config option | 72 | private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>(); |
66 | const string REDIRECT_URL = null; | 73 | private static Thread[] m_workerThreads = null; |
67 | 74 | ||
68 | private string m_URL; | 75 | private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue = |
76 | new OpenMetaverse.BlockingQueue<aPollRequest>(); | ||
69 | 77 | ||
70 | #region ISharedRegionModule Members | 78 | #region ISharedRegionModule Members |
71 | 79 | ||
72 | public void Initialise(IConfigSource source) | 80 | public void Initialise(IConfigSource source) |
73 | { | 81 | { |
74 | IConfig config = source.Configs["ClientStack.LindenCaps"]; | ||
75 | if (config == null) | ||
76 | return; | ||
77 | |||
78 | m_URL = config.GetString("Cap_GetTexture", string.Empty); | ||
79 | // Cap doesn't exist | ||
80 | if (m_URL != string.Empty) | ||
81 | m_Enabled = true; | ||
82 | } | 82 | } |
83 | 83 | ||
84 | public void AddRegion(Scene s) | 84 | public void AddRegion(Scene s) |
85 | { | 85 | { |
86 | if (!m_Enabled) | ||
87 | return; | ||
88 | |||
89 | m_scene = s; | 86 | m_scene = s; |
87 | m_assetService = s.AssetService; | ||
90 | } | 88 | } |
91 | 89 | ||
92 | public void RemoveRegion(Scene s) | 90 | public void RemoveRegion(Scene s) |
93 | { | 91 | { |
94 | if (!m_Enabled) | ||
95 | return; | ||
96 | |||
97 | m_scene.EventManager.OnRegisterCaps -= RegisterCaps; | 92 | m_scene.EventManager.OnRegisterCaps -= RegisterCaps; |
93 | m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps; | ||
98 | m_scene = null; | 94 | m_scene = null; |
99 | } | 95 | } |
100 | 96 | ||
101 | public void RegionLoaded(Scene s) | 97 | public void RegionLoaded(Scene s) |
102 | { | 98 | { |
103 | if (!m_Enabled) | 99 | // We'll reuse the same handler for all requests. |
104 | return; | 100 | m_getTextureHandler = new GetTextureHandler(m_assetService); |
105 | 101 | ||
106 | m_assetService = m_scene.RequestModuleInterface<IAssetService>(); | ||
107 | m_scene.EventManager.OnRegisterCaps += RegisterCaps; | 102 | m_scene.EventManager.OnRegisterCaps += RegisterCaps; |
103 | m_scene.EventManager.OnDeregisterCaps += DeregisterCaps; | ||
104 | |||
105 | if (m_workerThreads == null) | ||
106 | { | ||
107 | m_workerThreads = new Thread[4]; | ||
108 | |||
109 | for (uint i = 0; i < 4; i++) | ||
110 | { | ||
111 | m_workerThreads[i] = Watchdog.StartThread(DoTextureRequests, | ||
112 | String.Format("TextureWorkerThread{0}", i), | ||
113 | ThreadPriority.Normal, | ||
114 | false, | ||
115 | false, | ||
116 | null, | ||
117 | int.MaxValue); | ||
118 | } | ||
119 | } | ||
108 | } | 120 | } |
109 | 121 | ||
110 | public void PostInitialise() | 122 | public void PostInitialise() |
@@ -122,24 +134,152 @@ namespace OpenSim.Region.ClientStack.Linden | |||
122 | 134 | ||
123 | #endregion | 135 | #endregion |
124 | 136 | ||
125 | public void RegisterCaps(UUID agentID, Caps caps) | 137 | ~GetTextureModule() |
138 | { | ||
139 | foreach (Thread t in m_workerThreads) | ||
140 | Watchdog.AbortThread(t.ManagedThreadId); | ||
141 | |||
142 | } | ||
143 | |||
144 | private class PollServiceTextureEventArgs : PollServiceEventArgs | ||
145 | { | ||
146 | private List<Hashtable> requests = | ||
147 | new List<Hashtable>(); | ||
148 | private Dictionary<UUID, Hashtable> responses = | ||
149 | new Dictionary<UUID, Hashtable>(); | ||
150 | |||
151 | private Scene m_scene; | ||
152 | |||
153 | public PollServiceTextureEventArgs(UUID pId, Scene scene) : | ||
154 | base(null, null, null, null, pId, int.MaxValue) | ||
155 | { | ||
156 | m_scene = scene; | ||
157 | |||
158 | HasEvents = (x, y) => | ||
159 | { | ||
160 | lock (responses) | ||
161 | return responses.ContainsKey(x); | ||
162 | }; | ||
163 | GetEvents = (x, y) => | ||
164 | { | ||
165 | lock (responses) | ||
166 | { | ||
167 | try | ||
168 | { | ||
169 | return responses[x]; | ||
170 | } | ||
171 | finally | ||
172 | { | ||
173 | responses.Remove(x); | ||
174 | } | ||
175 | } | ||
176 | }; | ||
177 | |||
178 | Request = (x, y) => | ||
179 | { | ||
180 | aPollRequest reqinfo = new aPollRequest(); | ||
181 | reqinfo.thepoll = this; | ||
182 | reqinfo.reqID = x; | ||
183 | reqinfo.request = y; | ||
184 | |||
185 | m_queue.Enqueue(reqinfo); | ||
186 | }; | ||
187 | |||
188 | // this should never happen except possible on shutdown | ||
189 | NoEvents = (x, y) => | ||
190 | { | ||
191 | /* | ||
192 | lock (requests) | ||
193 | { | ||
194 | Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString()); | ||
195 | requests.Remove(request); | ||
196 | } | ||
197 | */ | ||
198 | Hashtable response = new Hashtable(); | ||
199 | |||
200 | response["int_response_code"] = 500; | ||
201 | response["str_response_string"] = "Script timeout"; | ||
202 | response["content_type"] = "text/plain"; | ||
203 | response["keepalive"] = false; | ||
204 | response["reusecontext"] = false; | ||
205 | |||
206 | return response; | ||
207 | }; | ||
208 | } | ||
209 | |||
210 | public void Process(aPollRequest requestinfo) | ||
211 | { | ||
212 | Hashtable response; | ||
213 | |||
214 | UUID requestID = requestinfo.reqID; | ||
215 | |||
216 | // If the avatar is gone, don't bother to get the texture | ||
217 | if (m_scene.GetScenePresence(Id) == null) | ||
218 | { | ||
219 | response = new Hashtable(); | ||
220 | |||
221 | response["int_response_code"] = 500; | ||
222 | response["str_response_string"] = "Script timeout"; | ||
223 | response["content_type"] = "text/plain"; | ||
224 | response["keepalive"] = false; | ||
225 | response["reusecontext"] = false; | ||
226 | |||
227 | lock (responses) | ||
228 | responses[requestID] = response; | ||
229 | |||
230 | return; | ||
231 | } | ||
232 | |||
233 | response = m_getTextureHandler.Handle(requestinfo.request); | ||
234 | lock (responses) | ||
235 | responses[requestID] = response; | ||
236 | } | ||
237 | } | ||
238 | |||
239 | private void RegisterCaps(UUID agentID, Caps caps) | ||
126 | { | 240 | { |
127 | UUID capID = UUID.Random(); | 241 | string capUrl = "/CAPS/" + UUID.Random() + "/"; |
242 | |||
243 | // Register this as a poll service | ||
244 | PollServiceTextureEventArgs args = new PollServiceTextureEventArgs(agentID, m_scene); | ||
245 | |||
246 | args.Type = PollServiceEventArgs.EventType.Texture; | ||
247 | MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); | ||
128 | 248 | ||
129 | //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture)); | 249 | string hostName = m_scene.RegionInfo.ExternalHostName; |
130 | if (m_URL == "localhost") | 250 | uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port; |
251 | string protocol = "http"; | ||
252 | |||
253 | if (MainServer.Instance.UseSSL) | ||
131 | { | 254 | { |
132 | // m_log.DebugFormat("[GETTEXTURE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); | 255 | hostName = MainServer.Instance.SSLCommonName; |
133 | caps.RegisterHandler( | 256 | port = MainServer.Instance.SSLPort; |
134 | "GetTexture", | 257 | protocol = "https"; |
135 | new GetTextureHandler("/CAPS/" + capID + "/", m_assetService, "GetTexture", agentID.ToString())); | ||
136 | } | 258 | } |
137 | else | 259 | caps.RegisterHandler("GetTexture", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl)); |
260 | |||
261 | m_capsDict[agentID] = capUrl; | ||
262 | } | ||
263 | |||
264 | private void DeregisterCaps(UUID agentID, Caps caps) | ||
265 | { | ||
266 | string capUrl; | ||
267 | |||
268 | if (m_capsDict.TryGetValue(agentID, out capUrl)) | ||
138 | { | 269 | { |
139 | // m_log.DebugFormat("[GETTEXTURE]: {0} in region {1}", m_URL, m_scene.RegionInfo.RegionName); | 270 | MainServer.Instance.RemoveHTTPHandler("", capUrl); |
140 | caps.RegisterHandler("GetTexture", m_URL); | 271 | m_capsDict.Remove(agentID); |
141 | } | 272 | } |
142 | } | 273 | } |
143 | 274 | ||
275 | private void DoTextureRequests() | ||
276 | { | ||
277 | while (true) | ||
278 | { | ||
279 | aPollRequest poolreq = m_queue.Dequeue(); | ||
280 | |||
281 | poolreq.thepoll.Process(poolreq); | ||
282 | } | ||
283 | } | ||
144 | } | 284 | } |
145 | } | 285 | } |