aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs (renamed from OpenSim/Region/Environment/Modules/ScriptsHttpRequests.cs)720
1 files changed, 356 insertions, 364 deletions
diff --git a/OpenSim/Region/Environment/Modules/ScriptsHttpRequests.cs b/OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index 2de5975..4977a86 100644
--- a/OpenSim/Region/Environment/Modules/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -1,364 +1,356 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the 12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 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 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 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Net; 31using System.Net;
32using System.Text; 32using System.Text;
33using System.Threading; 33using System.Threading;
34using libsecondlife; 34using libsecondlife;
35using Nini.Config; 35using Nini.Config;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using OpenSim.Region.Environment.Interfaces; 37using OpenSim.Region.Environment.Interfaces;
38using OpenSim.Region.Environment.Scenes; 38using OpenSim.Region.Environment.Scenes;
39 39
40/***************************************************** 40/*****************************************************
41 * 41 *
42 * ScriptsHttpRequests 42 * ScriptsHttpRequests
43 * 43 *
44 * Implements the llHttpRequest and http_response 44 * Implements the llHttpRequest and http_response
45 * callback. 45 * callback.
46 * 46 *
47 * Some stuff was already in LSLLongCmdHandler, and then 47 * Some stuff was already in LSLLongCmdHandler, and then
48 * there was this file with a stub class in it. So, 48 * there was this file with a stub class in it. So,
49 * I am moving some of the objects and functions out of 49 * I am moving some of the objects and functions out of
50 * LSLLongCmdHandler, such as the HttpRequestClass, the 50 * LSLLongCmdHandler, such as the HttpRequestClass, the
51 * start and stop methods, and setting up pending and 51 * start and stop methods, and setting up pending and
52 * completed queues. These are processed in the 52 * completed queues. These are processed in the
53 * LSLLongCmdHandler polling loop. Similiar to the 53 * LSLLongCmdHandler polling loop. Similiar to the
54 * XMLRPCModule, since that seems to work. 54 * XMLRPCModule, since that seems to work.
55 * 55 *
56 * //TODO 56 * //TODO
57 * 57 *
58 * This probably needs some throttling mechanism but 58 * This probably needs some throttling mechanism but
59 * its wide open right now. This applies to both 59 * its wide open right now. This applies to both
60 * number of requests and data volume. 60 * number of requests and data volume.
61 * 61 *
62 * Linden puts all kinds of header fields in the requests. 62 * Linden puts all kinds of header fields in the requests.
63 * Not doing any of that: 63 * Not doing any of that:
64 * User-Agent 64 * User-Agent
65 * X-SecondLife-Shard 65 * X-SecondLife-Shard
66 * X-SecondLife-Object-Name 66 * X-SecondLife-Object-Name
67 * X-SecondLife-Object-Key 67 * X-SecondLife-Object-Key
68 * X-SecondLife-Region 68 * X-SecondLife-Region
69 * X-SecondLife-Local-Position 69 * X-SecondLife-Local-Position
70 * X-SecondLife-Local-Velocity 70 * X-SecondLife-Local-Velocity
71 * X-SecondLife-Local-Rotation 71 * X-SecondLife-Local-Rotation
72 * X-SecondLife-Owner-Name 72 * X-SecondLife-Owner-Name
73 * X-SecondLife-Owner-Key 73 * X-SecondLife-Owner-Key
74 * 74 *
75 * HTTPS support 75 * HTTPS support
76 * 76 *
77 * Configurable timeout? 77 * Configurable timeout?
78 * Configurable max repsonse size? 78 * Configurable max repsonse size?
79 * Configurable 79 * Configurable
80 * 80 *
81 * **************************************************/ 81 * **************************************************/
82 82
83namespace OpenSim.Region.Environment.Modules 83namespace OpenSim.Region.Environment.Modules.Scripting.HttpRequest
84{ 84{
85 public class ScriptHTTPRequests : IRegionModule, IHttpRequests 85 public class HttpRequestModule : IRegionModule, IHttpRequests
86 { 86 {
87 private Scene m_scene; 87 private Scene m_scene;
88 private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>(); 88 private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>();
89 private object HttpListLock = new object(); 89 private object HttpListLock = new object();
90 private string m_name = "HttpScriptRequests"; 90 private string m_name = "HttpScriptRequests";
91 private int httpTimeout = 30000; 91 private int httpTimeout = 30000;
92 92
93 // <request id, HttpRequestClass> 93 // <request id, HttpRequestClass>
94 private Dictionary<LLUUID, HttpRequestClass> m_pendingRequests; 94 private Dictionary<LLUUID, HttpRequestClass> m_pendingRequests;
95 95
96 public ScriptHTTPRequests() 96 public HttpRequestModule()
97 { 97 {
98 } 98 }
99 99
100 public void Initialise(Scene scene, IConfigSource config) 100 public void Initialise(Scene scene, IConfigSource config)
101 { 101 {
102 m_scene = scene; 102 m_scene = scene;
103 103
104 m_scene.RegisterModuleInterface<IHttpRequests>(this); 104 m_scene.RegisterModuleInterface<IHttpRequests>(this);
105 105
106 m_pendingRequests = new Dictionary<LLUUID, HttpRequestClass>(); 106 m_pendingRequests = new Dictionary<LLUUID, HttpRequestClass>();
107 } 107 }
108 108
109 public void PostInitialise() 109 public void PostInitialise()
110 { 110 {
111 } 111 }
112 112
113 public void Close() 113 public void Close()
114 { 114 {
115 } 115 }
116 116
117 public string Name 117 public string Name
118 { 118 {
119 get { return m_name; } 119 get { return m_name; }
120 } 120 }
121 121
122 public bool IsSharedModule 122 public bool IsSharedModule
123 { 123 {
124 get { return true; } 124 get { return true; }
125 } 125 }
126 126
127 public LLUUID MakeHttpRequest(string url, string parameters, string body) 127 public LLUUID MakeHttpRequest(string url, string parameters, string body)
128 { 128 {
129 return LLUUID.Zero; 129 return LLUUID.Zero;
130 } 130 }
131 131
132 public LLUUID StartHttpRequest(uint localID, LLUUID itemID, string url, List<string> parameters, string body) 132 public LLUUID StartHttpRequest(uint localID, LLUUID itemID, string url, List<string> parameters, string body)
133 { 133 {
134 LLUUID reqID = LLUUID.Random(); 134 LLUUID reqID = LLUUID.Random();
135 HttpRequestClass htc = new HttpRequestClass(); 135 HttpRequestClass htc = new HttpRequestClass();
136 136
137 // Partial implementation: support for parameter flags needed 137 // Partial implementation: support for parameter flags needed
138 // see http://wiki.secondlife.com/wiki/LlHTTPRequest 138 // see http://wiki.secondlife.com/wiki/LlHTTPRequest
139 // 139 //
140 // Parameters are expected in {key, value, ... , key, value} 140 // Parameters are expected in {key, value, ... , key, value}
141 if (parameters != null) 141 if (parameters != null)
142 { 142 {
143 string[] parms = parameters.ToArray(); 143 string[] parms = parameters.ToArray();
144 for (int i = 0; i < parms.Length/2; i += 2) 144 for (int i = 0; i < parms.Length/2; i += 2)
145 { 145 {
146 switch (Int32.Parse(parms[i])) 146 switch (Int32.Parse(parms[i]))
147 { 147 {
148 case HttpRequestClass.HTTP_METHOD: 148 case HttpRequestClass.HTTP_METHOD:
149 149
150 htc.httpMethod = parms[i + 1]; 150 htc.httpMethod = parms[i + 1];
151 break; 151 break;
152 152
153 case HttpRequestClass.HTTP_MIMETYPE: 153 case HttpRequestClass.HTTP_MIMETYPE:
154 154
155 htc.httpMIMEType = parms[i + 1]; 155 htc.httpMIMEType = parms[i + 1];
156 break; 156 break;
157 157
158 case HttpRequestClass.HTTP_BODY_MAXLENGTH: 158 case HttpRequestClass.HTTP_BODY_MAXLENGTH:
159 159
160 // TODO implement me 160 // TODO implement me
161 break; 161 break;
162 162
163 case HttpRequestClass.HTTP_VERIFY_CERT: 163 case HttpRequestClass.HTTP_VERIFY_CERT:
164 164
165 // TODO implement me 165 // TODO implement me
166 break; 166 break;
167 } 167 }
168 } 168 }
169 } 169 }
170 170
171 htc.localID = localID; 171 htc.localID = localID;
172 htc.itemID = itemID; 172 htc.itemID = itemID;
173 htc.url = url; 173 htc.url = url;
174 htc.reqID = reqID; 174 htc.reqID = reqID;
175 htc.httpTimeout = httpTimeout; 175 htc.httpTimeout = httpTimeout;
176 htc.outbound_body = body; 176 htc.outbound_body = body;
177 177
178 lock (HttpListLock) 178 lock (HttpListLock)
179 { 179 {
180 m_pendingRequests.Add(reqID, htc); 180 m_pendingRequests.Add(reqID, htc);
181 } 181 }
182 182
183 htc.process(); 183 htc.process();
184 184
185 return reqID; 185 return reqID;
186 } 186 }
187 187
188 public void StopHttpRequest(uint m_localID, LLUUID m_itemID) 188 public void StopHttpRequest(uint m_localID, LLUUID m_itemID)
189 { 189 {
190 if(m_pendingRequests != null) { 190 if(m_pendingRequests != null) {
191 lock (HttpListLock) 191 lock (HttpListLock)
192 { 192 {
193 HttpRequestClass tmpReq; 193 HttpRequestClass tmpReq;
194 if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq)) 194 if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq))
195 { 195 {
196 tmpReq.Stop(); 196 tmpReq.Stop();
197 m_pendingRequests.Remove(m_itemID); 197 m_pendingRequests.Remove(m_itemID);
198 } 198 }
199 } 199 }
200 } 200 }
201 } 201 }
202 202
203 /* 203 /*
204 * TODO 204 * TODO
205 * Not sure how important ordering is is here - the next first 205 * Not sure how important ordering is is here - the next first
206 * one completed in the list is returned, based soley on its list 206 * one completed in the list is returned, based soley on its list
207 * position, not the order in which the request was started or 207 * position, not the order in which the request was started or
208 * finsihed. I thought about setting up a queue for this, but 208 * finsihed. I thought about setting up a queue for this, but
209 * it will need some refactoring and this works 'enough' right now 209 * it will need some refactoring and this works 'enough' right now
210 */ 210 */
211 211
212 public HttpRequestClass GetNextCompletedRequest() 212 public HttpRequestClass GetNextCompletedRequest()
213 { 213 {
214 lock (HttpListLock) 214 lock (HttpListLock)
215 { 215 {
216 foreach (LLUUID luid in m_pendingRequests.Keys) 216 foreach (LLUUID luid in m_pendingRequests.Keys)
217 { 217 {
218 HttpRequestClass tmpReq; 218 HttpRequestClass tmpReq;
219 219
220 if (m_pendingRequests.TryGetValue(luid, out tmpReq)) 220 if (m_pendingRequests.TryGetValue(luid, out tmpReq))
221 { 221 {
222 if (tmpReq.finished) 222 if (tmpReq.finished)
223 { 223 {
224 return tmpReq; 224 return tmpReq;
225 } 225 }
226 } 226 }
227 } 227 }
228 } 228 }
229 return null; 229 return null;
230 } 230 }
231 231
232 public void RemoveCompletedRequest(LLUUID id) 232 public void RemoveCompletedRequest(LLUUID id)
233 { 233 {
234 lock (HttpListLock) 234 lock (HttpListLock)
235 { 235 {
236 HttpRequestClass tmpReq; 236 HttpRequestClass tmpReq;
237 if (m_pendingRequests.TryGetValue(id, out tmpReq)) 237 if (m_pendingRequests.TryGetValue(id, out tmpReq))
238 { 238 {
239 tmpReq.Stop(); 239 tmpReq.Stop();
240 tmpReq = null; 240 tmpReq = null;
241 m_pendingRequests.Remove(id); 241 m_pendingRequests.Remove(id);
242 } 242 }
243 } 243 }
244 } 244 }
245 245
246 } 246 }
247 247
248 // 248 public class HttpRequestClass
249 // HTTP REAQUEST 249 {
250 // This class was originally in LSLLongCmdHandler 250 // Constants for parameters
251 // 251 public const int HTTP_METHOD = 0;
252 // TODO: setter/getter methods, maybe pass some in 252 public const int HTTP_MIMETYPE = 1;
253 // constructor 253 public const int HTTP_BODY_MAXLENGTH = 2;
254 // 254 public const int HTTP_VERIFY_CERT = 3;
255 255
256 public class HttpRequestClass 256 // Parameter members and default values
257 { 257 public string httpMethod = "GET";
258 // Constants for parameters 258 public string httpMIMEType = "text/plain;charset=utf-8";
259 public const int HTTP_METHOD = 0; 259 public int httpBodyMaxLen = 2048; // not implemented
260 public const int HTTP_MIMETYPE = 1; 260 public bool httpVerifyCert = true; // not implemented
261 public const int HTTP_BODY_MAXLENGTH = 2; 261
262 public const int HTTP_VERIFY_CERT = 3; 262 // Request info
263 263 public uint localID;
264 // Parameter members and default values 264 public LLUUID itemID;
265 public string httpMethod = "GET"; 265 public LLUUID reqID;
266 public string httpMIMEType = "text/plain;charset=utf-8"; 266 public int httpTimeout;
267 public int httpBodyMaxLen = 2048; // not implemented 267 public string url;
268 public bool httpVerifyCert = true; // not implemented 268 public string outbound_body;
269 269 public DateTime next;
270 // Request info 270 public int status;
271 public uint localID; 271 public bool finished;
272 public LLUUID itemID; 272 public List<string> response_metadata;
273 public LLUUID reqID; 273 public string response_body;
274 public int httpTimeout; 274 public HttpWebRequest request;
275 public string url; 275 private Thread httpThread;
276 public string outbound_body; 276
277 public DateTime next; 277 public void process()
278 public int status; 278 {
279 public bool finished; 279 httpThread = new Thread(SendRequest);
280 public List<string> response_metadata; 280 httpThread.Name = "HttpRequestThread";
281 public string response_body; 281 httpThread.Priority = ThreadPriority.BelowNormal;
282 public HttpWebRequest request; 282 httpThread.IsBackground = true;
283 private Thread httpThread; 283 finished = false;
284 284 httpThread.Start();
285 public void process() 285 ThreadTracker.Add(httpThread);
286 { 286 }
287 httpThread = new Thread(SendRequest); 287
288 httpThread.Name = "HttpRequestThread"; 288 /*
289 httpThread.Priority = ThreadPriority.BelowNormal; 289 * TODO: More work on the response codes. Right now
290 httpThread.IsBackground = true; 290 * returning 200 for success or 499 for exception
291 finished = false; 291 */
292 httpThread.Start(); 292
293 ThreadTracker.Add(httpThread); 293 public void SendRequest()
294 } 294 {
295 295 HttpWebResponse response = null;
296 /* 296 StringBuilder sb = new StringBuilder();
297 * TODO: More work on the response codes. Right now 297 byte[] buf = new byte[8192];
298 * returning 200 for success or 499 for exception 298 string tempString = null;
299 */ 299 int count = 0;
300 300
301 public void SendRequest() 301 try
302 { 302 {
303 HttpWebResponse response = null; 303 request = (HttpWebRequest)
304 StringBuilder sb = new StringBuilder(); 304 WebRequest.Create(url);
305 byte[] buf = new byte[8192]; 305 request.Method = httpMethod;
306 string tempString = null; 306 request.ContentType = httpMIMEType;
307 int count = 0; 307
308 308 request.Timeout = httpTimeout;
309 try 309 // execute the request
310 { 310 response = (HttpWebResponse)
311 request = (HttpWebRequest) 311 request.GetResponse();
312 WebRequest.Create(url); 312
313 request.Method = httpMethod; 313 Stream resStream = response.GetResponseStream();
314 request.ContentType = httpMIMEType; 314
315 315 do
316 request.Timeout = httpTimeout; 316 {
317 // execute the request 317 // fill the buffer with data
318 response = (HttpWebResponse) 318 count = resStream.Read(buf, 0, buf.Length);
319 request.GetResponse(); 319
320 320 // make sure we read some data
321 Stream resStream = response.GetResponseStream(); 321 if (count != 0)
322 322 {
323 do 323 // translate from bytes to ASCII text
324 { 324 tempString = Encoding.UTF8.GetString(buf, 0, count);
325 // fill the buffer with data 325
326 count = resStream.Read(buf, 0, buf.Length); 326 // continue building the string
327 327 sb.Append(tempString);
328 // make sure we read some data 328 }
329 if (count != 0) 329 } while (count > 0); // any more data to read?
330 { 330
331 // translate from bytes to ASCII text 331 response_body = sb.ToString();
332 tempString = Encoding.UTF8.GetString(buf, 0, count); 332 }
333 333 catch (Exception e)
334 // continue building the string 334 {
335 sb.Append(tempString); 335 status = 499;
336 } 336 response_body = e.Message;
337 } while (count > 0); // any more data to read? 337 finished = true;
338 338 return;
339 response_body = sb.ToString(); 339 }
340 } 340
341 catch (Exception e) 341 status = 200;
342 { 342 finished = true;
343 status = 499; 343 }
344 response_body = e.Message; 344
345 finished = true; 345 public void Stop()
346 return; 346 {
347 } 347 try
348 348 {
349 status = 200; 349 httpThread.Abort();
350 finished = true; 350 }
351 } 351 catch (Exception)
352 352 {
353 public void Stop() 353 }
354 { 354 }
355 try 355 }
356 { 356} \ No newline at end of file
357 httpThread.Abort();
358 }
359 catch (Exception)
360 {
361 }
362 }
363 }
364}