diff options
9 files changed, 342 insertions, 113 deletions
diff --git a/OpenSim/Framework/Console/RemoteConsole.cs b/OpenSim/Framework/Console/RemoteConsole.cs index 76276a5..c27072c 100644 --- a/OpenSim/Framework/Console/RemoteConsole.cs +++ b/OpenSim/Framework/Console/RemoteConsole.cs | |||
@@ -198,7 +198,7 @@ namespace OpenSim.Framework.Console | |||
198 | string uri = "/ReadResponses/" + sessionID.ToString() + "/"; | 198 | string uri = "/ReadResponses/" + sessionID.ToString() + "/"; |
199 | 199 | ||
200 | m_Server.AddPollServiceHTTPHandler(uri, HandleHttpPoll, | 200 | m_Server.AddPollServiceHTTPHandler(uri, HandleHttpPoll, |
201 | new PollServiceEventArgs(HasEvents, GetEvents, NoEvents, | 201 | new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, |
202 | sessionID)); | 202 | sessionID)); |
203 | 203 | ||
204 | XmlDocument xmldoc = new XmlDocument(); | 204 | XmlDocument xmldoc = new XmlDocument(); |
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 5d83e34..db87958 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs | |||
@@ -256,17 +256,51 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
256 | IHttpClientContext context = (IHttpClientContext)source; | 256 | IHttpClientContext context = (IHttpClientContext)source; |
257 | IHttpRequest request = args.Request; | 257 | IHttpRequest request = args.Request; |
258 | 258 | ||
259 | |||
260 | PollServiceEventArgs psEvArgs; | 259 | PollServiceEventArgs psEvArgs; |
260 | |||
261 | if (TryGetPollServiceHTTPHandler(request.UriPath.ToString(), out psEvArgs)) | 261 | if (TryGetPollServiceHTTPHandler(request.UriPath.ToString(), out psEvArgs)) |
262 | { | 262 | { |
263 | OSHttpRequest req = new OSHttpRequest(context, request); | ||
264 | |||
265 | PollServiceHttpRequest psreq = new PollServiceHttpRequest(psEvArgs, context, request); | 263 | PollServiceHttpRequest psreq = new PollServiceHttpRequest(psEvArgs, context, request); |
266 | req.Headers["X-PollServiceID"] = psreq.RequestID.ToString(); | 264 | |
267 | HandleRequest(req, null); | 265 | if (psEvArgs.Request != null) |
266 | { | ||
267 | OSHttpRequest req = new OSHttpRequest(context, request); | ||
268 | |||
269 | Stream requestStream = req.InputStream; | ||
270 | |||
271 | Encoding encoding = Encoding.UTF8; | ||
272 | StreamReader reader = new StreamReader(requestStream, encoding); | ||
273 | |||
274 | string requestBody = reader.ReadToEnd(); | ||
275 | |||
276 | Hashtable keysvals = new Hashtable(); | ||
277 | Hashtable headervals = new Hashtable(); | ||
278 | |||
279 | string[] querystringkeys = req.QueryString.AllKeys; | ||
280 | string[] rHeaders = req.Headers.AllKeys; | ||
281 | |||
282 | keysvals.Add("body", requestBody); | ||
283 | keysvals.Add("uri", req.RawUrl); | ||
284 | keysvals.Add("content-type", req.ContentType); | ||
285 | keysvals.Add("http-method", req.HttpMethod); | ||
286 | |||
287 | foreach (string queryname in querystringkeys) | ||
288 | { | ||
289 | keysvals.Add(queryname, req.QueryString[queryname]); | ||
290 | } | ||
291 | |||
292 | foreach (string headername in rHeaders) | ||
293 | { | ||
294 | headervals[headername] = req.Headers[headername]; | ||
295 | } | ||
296 | |||
297 | keysvals.Add("headers",headervals); | ||
298 | keysvals.Add("querystringkeys", querystringkeys); | ||
299 | |||
300 | psEvArgs.Request(psreq.RequestID, keysvals); | ||
301 | } | ||
302 | |||
268 | m_PollServiceManager.Enqueue(psreq); | 303 | m_PollServiceManager.Enqueue(psreq); |
269 | //DoHTTPGruntWork(psEvArgs.NoEvents(),new OSHttpResponse(new HttpResponse(context, request))); | ||
270 | } | 304 | } |
271 | else | 305 | else |
272 | { | 306 | { |
@@ -279,48 +313,16 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
279 | { | 313 | { |
280 | OSHttpRequest req = new OSHttpRequest(context, request); | 314 | OSHttpRequest req = new OSHttpRequest(context, request); |
281 | OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); | 315 | OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); |
282 | //resp.KeepAlive = req.KeepAlive; | ||
283 | //m_log.Info("[Debug BASE HTTP SERVER]: Got Request"); | ||
284 | //HttpServerContextObj objstate= new HttpServerContextObj(req,resp); | ||
285 | //ThreadPool.QueueUserWorkItem(new WaitCallback(ConvertIHttpClientContextToOSHttp), (object)objstate); | ||
286 | HandleRequest(req, resp); | 316 | HandleRequest(req, resp); |
287 | } | 317 | } |
288 | 318 | ||
289 | public void ConvertIHttpClientContextToOSHttp(object stateinfo) | 319 | public void ConvertIHttpClientContextToOSHttp(object stateinfo) |
290 | { | 320 | { |
291 | HttpServerContextObj objstate = (HttpServerContextObj)stateinfo; | 321 | HttpServerContextObj objstate = (HttpServerContextObj)stateinfo; |
292 | //OSHttpRequest request = new OSHttpRequest(objstate.context,objstate.req); | ||
293 | //OSHttpResponse resp = new OSHttpResponse(new HttpServer.HttpResponse(objstate.context, objstate.req)); | ||
294 | 322 | ||
295 | OSHttpRequest request = objstate.oreq; | 323 | OSHttpRequest request = objstate.oreq; |
296 | OSHttpResponse resp = objstate.oresp; | 324 | OSHttpResponse resp = objstate.oresp; |
297 | //OSHttpResponse resp = new OSHttpResponse(new HttpServer.HttpResponse(objstate.context, objstate.req)); | ||
298 | 325 | ||
299 | /* | ||
300 | request.AcceptTypes = objstate.req.AcceptTypes; | ||
301 | request.ContentLength = (long)objstate.req.ContentLength; | ||
302 | request.Headers = objstate.req.Headers; | ||
303 | request.HttpMethod = objstate.req.Method; | ||
304 | request.InputStream = objstate.req.Body; | ||
305 | foreach (string str in request.Headers) | ||
306 | { | ||
307 | if (str.ToLower().Contains("content-type: ")) | ||
308 | { | ||
309 | request.ContentType = str.Substring(13, str.Length - 13); | ||
310 | break; | ||
311 | } | ||
312 | } | ||
313 | //request.KeepAlive = objstate.req. | ||
314 | foreach (HttpServer.HttpInput httpinput in objstate.req.QueryString) | ||
315 | { | ||
316 | request.QueryString.Add(httpinput.Name, httpinput[httpinput.Name]); | ||
317 | } | ||
318 | |||
319 | //request.Query = objstate.req.//objstate.req.QueryString; | ||
320 | //foreach ( | ||
321 | //request.QueryString = objstate.req.QueryString; | ||
322 | |||
323 | */ | ||
324 | HandleRequest(request,resp); | 326 | HandleRequest(request,resp); |
325 | } | 327 | } |
326 | 328 | ||
@@ -337,24 +339,19 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
337 | // handled | 339 | // handled |
338 | //m_log.Debug("[BASE HTTP SERVER]: Handling Request" + request.RawUrl); | 340 | //m_log.Debug("[BASE HTTP SERVER]: Handling Request" + request.RawUrl); |
339 | 341 | ||
340 | // If the response is null, then we're not going to respond here. This case | 342 | IHttpAgentHandler agentHandler; |
341 | // triggers when we're at the head of a HTTP poll | ||
342 | // | ||
343 | if (response != null) | ||
344 | { | ||
345 | IHttpAgentHandler agentHandler; | ||
346 | 343 | ||
347 | if (TryGetAgentHandler(request, response, out agentHandler)) | 344 | if (TryGetAgentHandler(request, response, out agentHandler)) |
345 | { | ||
346 | if (HandleAgentRequest(agentHandler, request, response)) | ||
348 | { | 347 | { |
349 | if (HandleAgentRequest(agentHandler, request, response)) | 348 | return; |
350 | { | ||
351 | return; | ||
352 | } | ||
353 | } | 349 | } |
354 | |||
355 | //response.KeepAlive = true; | ||
356 | response.SendChunked = false; | ||
357 | } | 350 | } |
351 | |||
352 | //response.KeepAlive = true; | ||
353 | response.SendChunked = false; | ||
354 | |||
358 | IRequestHandler requestHandler; | 355 | IRequestHandler requestHandler; |
359 | 356 | ||
360 | string path = request.RawUrl; | 357 | string path = request.RawUrl; |
@@ -368,8 +365,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
368 | // Okay, so this is bad, but should be considered temporary until everything is IStreamHandler. | 365 | // Okay, so this is bad, but should be considered temporary until everything is IStreamHandler. |
369 | byte[] buffer = null; | 366 | byte[] buffer = null; |
370 | 367 | ||
371 | if (response != null) | 368 | response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type. |
372 | response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type. | ||
373 | 369 | ||
374 | 370 | ||
375 | if (requestHandler is IStreamedRequestHandler) | 371 | if (requestHandler is IStreamedRequestHandler) |
@@ -425,12 +421,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
425 | //m_log.Warn("[HTTP]: " + requestBody); | 421 | //m_log.Warn("[HTTP]: " + requestBody); |
426 | 422 | ||
427 | } | 423 | } |
428 | // If we're not responding, we dont' care about the reply | 424 | DoHTTPGruntWork(HTTPRequestHandler.Handle(path, keysvals), response); |
429 | // | ||
430 | if (response == null) | ||
431 | HTTPRequestHandler.Handle(path, keysvals); | ||
432 | else | ||
433 | DoHTTPGruntWork(HTTPRequestHandler.Handle(path, keysvals), response); | ||
434 | return; | 425 | return; |
435 | } | 426 | } |
436 | else | 427 | else |
@@ -445,11 +436,6 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
445 | } | 436 | } |
446 | } | 437 | } |
447 | 438 | ||
448 | // The handler has run and we're not yet ready to respond, bail | ||
449 | // | ||
450 | if (response == null) | ||
451 | return; | ||
452 | |||
453 | request.InputStream.Close(); | 439 | request.InputStream.Close(); |
454 | 440 | ||
455 | // HTTP IN support. The script engine taes it from here | 441 | // HTTP IN support. The script engine taes it from here |
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs index 61cb8aa..9d512c6 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs | |||
@@ -30,6 +30,7 @@ using System.Collections; | |||
30 | using OpenMetaverse; | 30 | using OpenMetaverse; |
31 | namespace OpenSim.Framework.Servers.HttpServer | 31 | namespace OpenSim.Framework.Servers.HttpServer |
32 | { | 32 | { |
33 | public delegate void RequestMethod(UUID requestID, Hashtable request); | ||
33 | public delegate bool HasEventsMethod(UUID requestID, UUID pId); | 34 | public delegate bool HasEventsMethod(UUID requestID, UUID pId); |
34 | 35 | ||
35 | public delegate Hashtable GetEventsMethod(UUID requestID, UUID pId, string request); | 36 | public delegate Hashtable GetEventsMethod(UUID requestID, UUID pId, string request); |
@@ -41,9 +42,11 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
41 | public HasEventsMethod HasEvents; | 42 | public HasEventsMethod HasEvents; |
42 | public GetEventsMethod GetEvents; | 43 | public GetEventsMethod GetEvents; |
43 | public NoEventsMethod NoEvents; | 44 | public NoEventsMethod NoEvents; |
45 | public RequestMethod Request; | ||
44 | public UUID Id; | 46 | public UUID Id; |
45 | public PollServiceEventArgs(HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,UUID pId) | 47 | public PollServiceEventArgs(RequestMethod pRequest, HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,UUID pId) |
46 | { | 48 | { |
49 | Request = pRequest; | ||
47 | HasEvents = pHasEvents; | 50 | HasEvents = pHasEvents; |
48 | GetEvents = pGetEvents; | 51 | GetEvents = pGetEvents; |
49 | NoEvents = pNoEvents; | 52 | NoEvents = pNoEvents; |
diff --git a/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs index 57c5198..0cdd9a8 100644 --- a/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs | |||
@@ -316,7 +316,7 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue | |||
316 | 316 | ||
317 | // This will persist this beyond the expiry of the caps handlers | 317 | // This will persist this beyond the expiry of the caps handlers |
318 | MainServer.Instance.AddPollServiceHTTPHandler( | 318 | MainServer.Instance.AddPollServiceHTTPHandler( |
319 | capsBase + EventQueueGetUUID.ToString() + "/", EventQueuePoll, new PollServiceEventArgs(HasEvents, GetEvents, NoEvents, agentID)); | 319 | capsBase + EventQueueGetUUID.ToString() + "/", EventQueuePoll, new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID)); |
320 | 320 | ||
321 | Random rnd = new Random(Environment.TickCount); | 321 | Random rnd = new Random(Environment.TickCount); |
322 | lock (m_ids) | 322 | lock (m_ids) |
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 | ||