aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs4
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs306
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs14
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs4
-rw-r--r--bin/OpenSim.ini.example4
6 files changed, 287 insertions, 47 deletions
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
index 7ed9e5c..9d512c6 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
@@ -44,9 +44,9 @@ namespace OpenSim.Framework.Servers.HttpServer
44 public NoEventsMethod NoEvents; 44 public NoEventsMethod NoEvents;
45 public RequestMethod Request; 45 public RequestMethod Request;
46 public UUID Id; 46 public UUID Id;
47 public PollServiceEventArgs(RequestMethod Request, HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,UUID pId) 47 public PollServiceEventArgs(RequestMethod pRequest, HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,UUID pId)
48 { 48 {
49 Request = Request; 49 Request = pRequest;
50 HasEvents = pHasEvents; 50 HasEvents = pHasEvents;
51 GetEvents = pGetEvents; 51 GetEvents = pGetEvents;
52 NoEvents = pNoEvents; 52 NoEvents = pNoEvents;
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)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 02be983..b631478 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -7838,8 +7838,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7838 public LSL_String llGetHTTPHeader(LSL_Key request_id, string header) 7838 public LSL_String llGetHTTPHeader(LSL_Key request_id, string header)
7839 { 7839 {
7840 m_host.AddScriptLPS(1); 7840 m_host.AddScriptLPS(1);
7841 NotImplemented("llGetHTTPHeader"); 7841
7842 return String.Empty; 7842 if (m_UrlModule != null)
7843 return m_UrlModule.GetHttpHeader(new UUID(request_id), header);
7844 return String.Empty;
7843 } 7845 }
7844 7846
7845 7847
@@ -9117,13 +9119,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9117 } 9119 }
9118 9120
9119 9121
9120 public void llHTTPResponse(string url, int status, string body) 9122 public void llHTTPResponse(LSL_Key id, int status, string body)
9121 { 9123 {
9122 // Partial implementation: support for parameter flags needed 9124 // Partial implementation: support for parameter flags needed
9123 // see http://wiki.secondlife.com/wiki/llHTTPResponse 9125 // see http://wiki.secondlife.com/wiki/llHTTPResponse
9124 9126
9125 m_host.AddScriptLPS(1); 9127 m_host.AddScriptLPS(1);
9126 NotImplemented("llHTTPResponse"); 9128
9129 if (m_UrlModule != null)
9130 m_UrlModule.HttpResponse(new UUID(id), status,body);
9127 } 9131 }
9128 9132
9129 public void llResetLandBanList() 9133 public void llResetLandBanList()
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
index 41358e5..a74e8da 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -201,7 +201,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
201 void llGroundRepel(double height, int water, double tau); 201 void llGroundRepel(double height, int water, double tau);
202 LSL_Vector llGroundSlope(LSL_Vector offset); 202 LSL_Vector llGroundSlope(LSL_Vector offset);
203 LSL_String llHTTPRequest(string url, LSL_List parameters, string body); 203 LSL_String llHTTPRequest(string url, LSL_List parameters, string body);
204 void llHTTPResponse(string url, int status, string body); 204 void llHTTPResponse(LSL_Key id, int status, string body);
205 LSL_String llInsertString(string dst, int position, string src); 205 LSL_String llInsertString(string dst, int position, string src);
206 void llInstantMessage(string user, string message); 206 void llInstantMessage(string user, string message);
207 LSL_String llIntegerToBase64(int number); 207 LSL_String llIntegerToBase64(int number);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
index 02ae281..a28e97b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
@@ -864,9 +864,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
864 return m_LSL_Functions.llHTTPRequest(url, parameters, body); 864 return m_LSL_Functions.llHTTPRequest(url, parameters, body);
865 } 865 }
866 866
867 public void llHTTPResponse(string url, int status, string body) 867 public void llHTTPResponse(LSL_Key id, int status, string body)
868 { 868 {
869 m_LSL_Functions.llHTTPResponse(url, status, body); 869 m_LSL_Functions.llHTTPResponse(id, status, body);
870 } 870 }
871 871
872 public LSL_String llInsertString(string dst, int position, string src) 872 public LSL_String llInsertString(string dst, int position, string src)
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index d38c511..e34378c 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -305,6 +305,10 @@
305 http_listener_sslport = 9001 ; Use this port for SSL connections 305 http_listener_sslport = 9001 ; Use this port for SSL connections
306 http_listener_ssl_cert = "" ; Currently unused, but will be used for OSHttpServer 306 http_listener_ssl_cert = "" ; Currently unused, but will be used for OSHttpServer
307 307
308 ; Hostname to use in llRequestURL/llRequestSecureURL
309 ; if not defined - default machine name is being used
310 ; (on Windows this mean NETBIOS name - useably only inside local network)
311 ; ExternalHostNameForLSL=127.0.0.1
308 ; Uncomment below to enable llRemoteData/remote channels 312 ; Uncomment below to enable llRemoteData/remote channels
309 ; remoteDataPort = 20800 313 ; remoteDataPort = 20800
310 314