aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules
diff options
context:
space:
mode:
authorMelanie2009-09-22 17:04:34 +0100
committerMelanie2009-09-22 17:04:34 +0100
commit97c18caa766e2dd72b152b78827ef554f2054f8c (patch)
treea15d21864c95dbfecc2c6eafb3b74dd59f830b0a /OpenSim/Region/CoreModules
parentCompletely remove the prior implementation of the request event handling (diff)
downloadopensim-SC-97c18caa766e2dd72b152b78827ef554f2054f8c.zip
opensim-SC-97c18caa766e2dd72b152b78827ef554f2054f8c.tar.gz
opensim-SC-97c18caa766e2dd72b152b78827ef554f2054f8c.tar.bz2
opensim-SC-97c18caa766e2dd72b152b78827ef554f2054f8c.tar.xz
Thank you, Intari, for a patch that implements the missing pieces of
Http-in and makes the host name for URL generation configurable. Applied with changes: llGetSimulatorHostname was not changed, because the change breaks existing behavior and carries a data exposure risk. That value needs to be configurable, the proposed fixed change is not acceptable.
Diffstat (limited to 'OpenSim/Region/CoreModules')
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs306
1 files changed, 269 insertions, 37 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 6a2a6c8..2d81e4c 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -54,29 +54,42 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
54 { 54 {
55 public UUID requestID; 55 public UUID requestID;
56 public Dictionary<string, string> headers; 56 public Dictionary<string, string> headers;
57 public string body; 57 public string body;
58 public ManualResetEvent ev; 58 public int responseCode;
59 public string responseBody;
60 public ManualResetEvent ev;
61 public bool requestDone;
62 public int startTime;
63 public string uri;
59 } 64 }
60 65
61 public class UrlModule : ISharedRegionModule, IUrlModule 66 public class UrlModule : ISharedRegionModule, IUrlModule
62 { 67 {
63// private static readonly ILog m_log = 68 private static readonly ILog m_log =
64// LogManager.GetLogger( 69 LogManager.GetLogger(
65// MethodBase.GetCurrentMethod().DeclaringType); 70 MethodBase.GetCurrentMethod().DeclaringType);
66 71
67 private Dictionary<UUID, UrlData> m_RequestMap = 72 private Dictionary<UUID, UrlData> m_RequestMap =
68 new Dictionary<UUID, UrlData>(); 73 new Dictionary<UUID, UrlData>();
69 74
70 private Dictionary<string, UrlData> m_UrlMap = 75 private Dictionary<string, UrlData> m_UrlMap =
71 new Dictionary<string, UrlData>(); 76 new Dictionary<string, UrlData>();
77
72 78
73 private int m_TotalUrls = 100; 79 private int m_TotalUrls = 100;
74 80
75 private IHttpServer m_HttpServer = null; 81 private IHttpServer m_HttpServer = null;
82
83 private string m_ExternalHostNameForLSL = "";
76 84
77 public Type ReplaceableInterface 85 public Type ReplaceableInterface
78 { 86 {
79 get { return null; } 87 get { return null; }
88 }
89
90 private Hashtable HandleHttpPoll(Hashtable request)
91 {
92 return new Hashtable();
80 } 93 }
81 94
82 public string Name 95 public string Name
@@ -85,7 +98,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
85 } 98 }
86 99
87 public void Initialise(IConfigSource config) 100 public void Initialise(IConfigSource config)
88 { 101 {
102 m_ExternalHostNameForLSL = config.Configs["Network"].GetString("ExternalHostNameForLSL", System.Environment.MachineName);
89 } 103 }
90 104
91 public void PostInitialise() 105 public void PostInitialise()
@@ -116,8 +130,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
116 130
117 public void Close() 131 public void Close()
118 { 132 {
119 } 133 }
120
121 public UUID RequestURL(IScriptModule engine, SceneObjectPart host, UUID itemID) 134 public UUID RequestURL(IScriptModule engine, SceneObjectPart host, UUID itemID)
122 { 135 {
123 UUID urlcode = UUID.Random(); 136 UUID urlcode = UUID.Random();
@@ -128,8 +141,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
128 { 141 {
129 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); 142 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" });
130 return urlcode; 143 return urlcode;
131 } 144 }
132 string url = "http://"+System.Environment.MachineName+":"+m_HttpServer.Port.ToString()+"/lslhttp/"+urlcode.ToString()+"/"; 145 string url = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString() + "/";
133 146
134 UrlData urlData = new UrlData(); 147 UrlData urlData = new UrlData();
135 urlData.hostID = host.UUID; 148 urlData.hostID = host.UUID;
@@ -139,9 +152,14 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
139 urlData.urlcode = urlcode; 152 urlData.urlcode = urlcode;
140 urlData.requests = new Dictionary<UUID, RequestData>(); 153 urlData.requests = new Dictionary<UUID, RequestData>();
141 154
142 m_UrlMap[url] = urlData; 155
143 156 m_UrlMap[url] = urlData;
144 m_HttpServer.AddHTTPHandler("/lslhttp/"+urlcode.ToString()+"/", HttpRequestHandler); 157
158 string uri = "/lslhttp/" + urlcode.ToString() + "/";
159
160 m_HttpServer.AddPollServiceHTTPHandler(uri,HandleHttpPoll,
161 new PollServiceEventArgs(HttpRequestHandler,HasEvents, GetEvents, NoEvents,
162 urlcode));
145 163
146 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); 164 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url });
147 } 165 }
@@ -162,10 +180,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
162 { 180 {
163 lock (m_UrlMap) 181 lock (m_UrlMap)
164 { 182 {
165 UrlData data; 183 UrlData data;
166 184
167 if (!m_UrlMap.TryGetValue(url, out data)) 185 if (!m_UrlMap.TryGetValue(url, out data))
168 return; 186 {
187 return;
188 }
169 189
170 foreach (UUID req in data.requests.Keys) 190 foreach (UUID req in data.requests.Keys)
171 m_RequestMap.Remove(req); 191 m_RequestMap.Remove(req);
@@ -174,14 +194,38 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
174 m_UrlMap.Remove(url); 194 m_UrlMap.Remove(url);
175 } 195 }
176 } 196 }
177 197
178 public void HttpResponse(UUID request, int status, string body) 198 public void HttpResponse(UUID request, int status, string body)
179 { 199 {
200 if (m_RequestMap.ContainsKey(request))
201 {
202 UrlData urlData = m_RequestMap[request];
203 RequestData requestData=urlData.requests[request];
204 urlData.requests[request].responseCode = status;
205 urlData.requests[request].responseBody = body;
206 //urlData.requests[request].ev.Set();
207 urlData.requests[request].requestDone=true;
208 }
209 else
210 {
211 m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString());
212 }
180 } 213 }
181 214
182 public string GetHttpHeader(UUID request, string header) 215 public string GetHttpHeader(UUID requestId, string header)
183 { 216 {
184 return String.Empty; 217 if (m_RequestMap.ContainsKey(requestId))
218 {
219 UrlData urlData=m_RequestMap[requestId];
220 string value;
221 if (urlData.requests[requestId].headers.TryGetValue(header,out value))
222 return value;
223 }
224 else
225 {
226 m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId);
227 }
228 return String.Empty;
185 } 229 }
186 230
187 public int GetFreeUrls() 231 public int GetFreeUrls()
@@ -231,27 +275,215 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
231 foreach (string urlname in removeURLs) 275 foreach (string urlname in removeURLs)
232 m_UrlMap.Remove(urlname); 276 m_UrlMap.Remove(urlname);
233 } 277 }
234 } 278 }
279
235 280
236 private void RemoveUrl(UrlData data) 281 private void RemoveUrl(UrlData data)
237 { 282 {
238 m_HttpServer.RemoveHTTPHandler("", "/lslhttp/"+data.urlcode.ToString()+"/"); 283 m_HttpServer.RemoveHTTPHandler("", "/lslhttp/"+data.urlcode.ToString()+"/");
239 } 284 }
285
286 private Hashtable NoEvents(UUID requestID, UUID sessionID)
287 {
288 Hashtable response = new Hashtable();
289 UrlData url;
290 lock (m_RequestMap)
291 {
292 if (!m_RequestMap.ContainsKey(requestID))
293 return response;
294 url = m_RequestMap[requestID];
295 }
296
297 if (System.Environment.TickCount - url.requests[requestID].startTime > 25000)
298 {
299 response["int_response_code"] = 500;
300 response["str_response_string"] = "Script timeout";
301 response["content_type"] = "text/plain";
302 response["keepalive"] = false;
303 response["reusecontext"] = false;
304
305 //remove from map
306 lock (url)
307 {
308 url.requests.Remove(requestID);
309 m_RequestMap.Remove(requestID);
310 }
311
312 return response;
313 }
240 314
241 private Hashtable HttpRequestHandler(Hashtable request) 315
316 return response;
317 }
318
319 private bool HasEvents(UUID requestID, UUID sessionID)
242 { 320 {
243 string uri = request["uri"].ToString(); 321 UrlData url=null;
244 //A solution to this ugly mess would be to use only the /lslhttp/<UUID>/ part of the URI as the key.
245 UrlData url = m_UrlMap["http://"+System.Environment.MachineName+":"+m_HttpServer.Port.ToString()+uri];
246 322
247 //UUID.Random() below is a hack! Eventually we will do HTTP requests and responses properly. 323 lock (m_RequestMap)
248 url.engine.PostScriptEvent(url.itemID, "http_request", new Object[] { UUID.Random().ToString(), request["http-method"].ToString(), request["body"].ToString() }); 324 {
325 if (!m_RequestMap.ContainsKey(requestID))
326 {
327 return false;
328 }
329 url = m_RequestMap[requestID];
330 if (!url.requests.ContainsKey(requestID))
331 {
332 return false;
333 }
334 }
249 335
250 Hashtable response = new Hashtable(); 336 if (System.Environment.TickCount-url.requests[requestID].startTime>25000)
251 response["int_response_code"] = 200; 337 {
252 response["str_response_string"] = "This is a generic response as OpenSim does not yet support proper responses. Your request has been passed to the object."; 338 return true;
339 }
253 340
254 return response; 341 if (url.requests[requestID].requestDone)
342 return true;
343 else
344 return false;
345
346 }
347 private Hashtable GetEvents(UUID requestID, UUID sessionID, string request)
348 {
349 UrlData url = null;
350 RequestData requestData = null;
351
352 lock (m_RequestMap)
353 {
354 if (!m_RequestMap.ContainsKey(requestID))
355 return NoEvents(requestID,sessionID);
356 url = m_RequestMap[requestID];
357 requestData = url.requests[requestID];
358 }
359
360 if (!requestData.requestDone)
361 return NoEvents(requestID,sessionID);
362
363 Hashtable response = new Hashtable();
364
365 if (System.Environment.TickCount - requestData.startTime > 25000)
366 {
367 response["int_response_code"] = 500;
368 response["str_response_string"] = "Script timeout";
369 response["content_type"] = "text/plain";
370 response["keepalive"] = false;
371 response["reusecontext"] = false;
372 return response;
373 }
374 //put response
375 response["int_response_code"] = requestData.responseCode;
376 response["str_response_string"] = requestData.responseBody;
377 response["content_type"] = "text/plain";
378 response["keepalive"] = false;
379 response["reusecontext"] = false;
380
381 //remove from map
382 lock (url)
383 {
384 url.requests.Remove(requestID);
385 m_RequestMap.Remove(requestID);
386 }
387
388 return response;
389 }
390 public void HttpRequestHandler(UUID requestID, Hashtable request)
391 {
392 lock (request)
393 {
394 string uri = request["uri"].ToString();
395
396 try
397 {
398 Hashtable headers = (Hashtable)request["headers"];
399
400 string uri_full = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/";
401
402 int pos1 = uri.IndexOf("/");// /lslhttp
403 int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/
404 int pos3 = uri.IndexOf("/", pos2 + 1);// /lslhttp/<UUID>/
405 string uri_tmp = uri.Substring(0, pos3 + 1);
406 //HTTP server code doesn't provide us with QueryStrings
407 string pathInfo;
408 string queryString;
409 queryString = "";
410
411 pathInfo = uri.Substring(pos3);
412
413 UrlData url = m_UrlMap["http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp];
414
415 //for llGetHttpHeader support we need to store original URI here
416 //to make x-path-info / x-query-string / x-script-url / x-remote-ip headers
417 //as per http://wiki.secondlife.com/wiki/LlGetHTTPHeader
418
419 RequestData requestData = new RequestData();
420 requestData.requestID = requestID;
421 requestData.requestDone = false;
422 requestData.startTime = System.Environment.TickCount;
423 requestData.uri = uri;
424 if (requestData.headers == null)
425 requestData.headers = new Dictionary<string, string>();
426
427 foreach (DictionaryEntry header in headers)
428 {
429 string key = (string)header.Key;
430 string value = (string)header.Value;
431 requestData.headers.Add(key, value);
432 }
433 foreach (DictionaryEntry de in request)
434 {
435 if (de.Key.ToString() == "querystringkeys")
436 {
437 System.String[] keys = (System.String[])de.Value;
438 foreach (String key in keys)
439 {
440 if (request.ContainsKey(key))
441 {
442 string val = (String)request[key];
443 queryString = queryString + key + "=" + val + "&";
444 }
445 }
446 if (queryString.Length > 1)
447 queryString = queryString.Substring(0, queryString.Length - 1);
448
449 }
450
451 }
452
453 //if this machine is behind DNAT/port forwarding, currently this is being
454 //set to address of port forwarding router
455 requestData.headers["x-remote-ip"] = requestData.headers["remote_addr"];
456 requestData.headers["x-path-info"] = pathInfo;
457 requestData.headers["x-query-string"] = queryString;
458 requestData.headers["x-script-url"] = url.url;
459
460 requestData.ev = new ManualResetEvent(false);
461 lock (url.requests)
462 {
463 url.requests.Add(requestID, requestData);
464 }
465 lock (m_RequestMap)
466 {
467 //add to request map
468 m_RequestMap.Add(requestID, url);
469 }
470
471 url.engine.PostScriptEvent(url.itemID, "http_request", new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() });
472
473 //send initial response?
474 Hashtable response = new Hashtable();
475
476 return;
477
478 }
479 catch (Exception we)
480 {
481 //Hashtable response = new Hashtable();
482 m_log.Warn("[HttpRequestHandler]: http-in request failed");
483 m_log.Warn(we.Message);
484 m_log.Warn(we.StackTrace);
485 }
486 }
255 } 487 }
256 488
257 private void OnScriptReset(uint localID, UUID itemID) 489 private void OnScriptReset(uint localID, UUID itemID)