aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs')
-rw-r--r--OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs726
1 files changed, 363 insertions, 363 deletions
diff --git a/OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index 184e026..e1339a3 100644
--- a/OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -1,364 +1,364 @@
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.Scripting.HttpRequest 83namespace OpenSim.Region.Environment.Modules.Scripting.HttpRequest
84{ 84{
85 public class HttpRequestModule : IRegionModule, IHttpRequests 85 public class HttpRequestModule : IRegionModule, IHttpRequests
86 { 86 {
87 private object HttpListLock = new object(); 87 private object HttpListLock = new object();
88 private int httpTimeout = 30000; 88 private int httpTimeout = 30000;
89 private string m_name = "HttpScriptRequests"; 89 private string m_name = "HttpScriptRequests";
90 90
91 // <request id, HttpRequestClass> 91 // <request id, HttpRequestClass>
92 private Dictionary<LLUUID, HttpRequestClass> m_pendingRequests; 92 private Dictionary<LLUUID, HttpRequestClass> m_pendingRequests;
93 private Scene m_scene; 93 private Scene m_scene;
94 private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>(); 94 private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>();
95 95
96 public HttpRequestModule() 96 public HttpRequestModule()
97 { 97 {
98 } 98 }
99 99
100 #region IHttpRequests Members 100 #region IHttpRequests Members
101 101
102 public LLUUID MakeHttpRequest(string url, string parameters, string body) 102 public LLUUID MakeHttpRequest(string url, string parameters, string body)
103 { 103 {
104 return LLUUID.Zero; 104 return LLUUID.Zero;
105 } 105 }
106 106
107 public LLUUID StartHttpRequest(uint localID, LLUUID itemID, string url, List<string> parameters, string body) 107 public LLUUID StartHttpRequest(uint localID, LLUUID itemID, string url, List<string> parameters, string body)
108 { 108 {
109 LLUUID reqID = LLUUID.Random(); 109 LLUUID reqID = LLUUID.Random();
110 HttpRequestClass htc = new HttpRequestClass(); 110 HttpRequestClass htc = new HttpRequestClass();
111 111
112 // Partial implementation: support for parameter flags needed 112 // Partial implementation: support for parameter flags needed
113 // see http://wiki.secondlife.com/wiki/LlHTTPRequest 113 // see http://wiki.secondlife.com/wiki/LlHTTPRequest
114 // 114 //
115 // Parameters are expected in {key, value, ... , key, value} 115 // Parameters are expected in {key, value, ... , key, value}
116 if (parameters != null) 116 if (parameters != null)
117 { 117 {
118 string[] parms = parameters.ToArray(); 118 string[] parms = parameters.ToArray();
119 for (int i = 0; i < parms.Length / 2; i += 2) 119 for (int i = 0; i < parms.Length / 2; i += 2)
120 { 120 {
121 switch (Int32.Parse(parms[i])) 121 switch (Int32.Parse(parms[i]))
122 { 122 {
123 case HttpRequestClass.HTTP_METHOD: 123 case HttpRequestClass.HTTP_METHOD:
124 124
125 htc.httpMethod = parms[i + 1]; 125 htc.httpMethod = parms[i + 1];
126 break; 126 break;
127 127
128 case HttpRequestClass.HTTP_MIMETYPE: 128 case HttpRequestClass.HTTP_MIMETYPE:
129 129
130 htc.httpMIMEType = parms[i + 1]; 130 htc.httpMIMEType = parms[i + 1];
131 break; 131 break;
132 132
133 case HttpRequestClass.HTTP_BODY_MAXLENGTH: 133 case HttpRequestClass.HTTP_BODY_MAXLENGTH:
134 134
135 // TODO implement me 135 // TODO implement me
136 break; 136 break;
137 137
138 case HttpRequestClass.HTTP_VERIFY_CERT: 138 case HttpRequestClass.HTTP_VERIFY_CERT:
139 139
140 // TODO implement me 140 // TODO implement me
141 break; 141 break;
142 } 142 }
143 } 143 }
144 } 144 }
145 145
146 htc.localID = localID; 146 htc.localID = localID;
147 htc.itemID = itemID; 147 htc.itemID = itemID;
148 htc.url = url; 148 htc.url = url;
149 htc.reqID = reqID; 149 htc.reqID = reqID;
150 htc.httpTimeout = httpTimeout; 150 htc.httpTimeout = httpTimeout;
151 htc.outbound_body = body; 151 htc.outbound_body = body;
152 152
153 lock (HttpListLock) 153 lock (HttpListLock)
154 { 154 {
155 m_pendingRequests.Add(reqID, htc); 155 m_pendingRequests.Add(reqID, htc);
156 } 156 }
157 157
158 htc.process(); 158 htc.process();
159 159
160 return reqID; 160 return reqID;
161 } 161 }
162 162
163 public void StopHttpRequest(uint m_localID, LLUUID m_itemID) 163 public void StopHttpRequest(uint m_localID, LLUUID m_itemID)
164 { 164 {
165 if (m_pendingRequests != null) 165 if (m_pendingRequests != null)
166 { 166 {
167 lock (HttpListLock) 167 lock (HttpListLock)
168 { 168 {
169 HttpRequestClass tmpReq; 169 HttpRequestClass tmpReq;
170 if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq)) 170 if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq))
171 { 171 {
172 tmpReq.Stop(); 172 tmpReq.Stop();
173 m_pendingRequests.Remove(m_itemID); 173 m_pendingRequests.Remove(m_itemID);
174 } 174 }
175 } 175 }
176 } 176 }
177 } 177 }
178 178
179 /* 179 /*
180 * TODO 180 * TODO
181 * Not sure how important ordering is is here - the next first 181 * Not sure how important ordering is is here - the next first
182 * one completed in the list is returned, based soley on its list 182 * one completed in the list is returned, based soley on its list
183 * position, not the order in which the request was started or 183 * position, not the order in which the request was started or
184 * finsihed. I thought about setting up a queue for this, but 184 * finsihed. I thought about setting up a queue for this, but
185 * it will need some refactoring and this works 'enough' right now 185 * it will need some refactoring and this works 'enough' right now
186 */ 186 */
187 187
188 public HttpRequestClass GetNextCompletedRequest() 188 public HttpRequestClass GetNextCompletedRequest()
189 { 189 {
190 lock (HttpListLock) 190 lock (HttpListLock)
191 { 191 {
192 foreach (LLUUID luid in m_pendingRequests.Keys) 192 foreach (LLUUID luid in m_pendingRequests.Keys)
193 { 193 {
194 HttpRequestClass tmpReq; 194 HttpRequestClass tmpReq;
195 195
196 if (m_pendingRequests.TryGetValue(luid, out tmpReq)) 196 if (m_pendingRequests.TryGetValue(luid, out tmpReq))
197 { 197 {
198 if (tmpReq.finished) 198 if (tmpReq.finished)
199 { 199 {
200 return tmpReq; 200 return tmpReq;
201 } 201 }
202 } 202 }
203 } 203 }
204 } 204 }
205 return null; 205 return null;
206 } 206 }
207 207
208 public void RemoveCompletedRequest(LLUUID id) 208 public void RemoveCompletedRequest(LLUUID id)
209 { 209 {
210 lock (HttpListLock) 210 lock (HttpListLock)
211 { 211 {
212 HttpRequestClass tmpReq; 212 HttpRequestClass tmpReq;
213 if (m_pendingRequests.TryGetValue(id, out tmpReq)) 213 if (m_pendingRequests.TryGetValue(id, out tmpReq))
214 { 214 {
215 tmpReq.Stop(); 215 tmpReq.Stop();
216 tmpReq = null; 216 tmpReq = null;
217 m_pendingRequests.Remove(id); 217 m_pendingRequests.Remove(id);
218 } 218 }
219 } 219 }
220 } 220 }
221 221
222 #endregion 222 #endregion
223 223
224 #region IRegionModule Members 224 #region IRegionModule Members
225 225
226 public void Initialise(Scene scene, IConfigSource config) 226 public void Initialise(Scene scene, IConfigSource config)
227 { 227 {
228 m_scene = scene; 228 m_scene = scene;
229 229
230 m_scene.RegisterModuleInterface<IHttpRequests>(this); 230 m_scene.RegisterModuleInterface<IHttpRequests>(this);
231 231
232 m_pendingRequests = new Dictionary<LLUUID, HttpRequestClass>(); 232 m_pendingRequests = new Dictionary<LLUUID, HttpRequestClass>();
233 } 233 }
234 234
235 public void PostInitialise() 235 public void PostInitialise()
236 { 236 {
237 } 237 }
238 238
239 public void Close() 239 public void Close()
240 { 240 {
241 } 241 }
242 242
243 public string Name 243 public string Name
244 { 244 {
245 get { return m_name; } 245 get { return m_name; }
246 } 246 }
247 247
248 public bool IsSharedModule 248 public bool IsSharedModule
249 { 249 {
250 get { return true; } 250 get { return true; }
251 } 251 }
252 252
253 #endregion 253 #endregion
254 } 254 }
255 255
256 public class HttpRequestClass 256 public class HttpRequestClass
257 { 257 {
258 // Constants for parameters 258 // Constants for parameters
259 public const int HTTP_BODY_MAXLENGTH = 2; 259 public const int HTTP_BODY_MAXLENGTH = 2;
260 public const int HTTP_METHOD = 0; 260 public const int HTTP_METHOD = 0;
261 public const int HTTP_MIMETYPE = 1; 261 public const int HTTP_MIMETYPE = 1;
262 public const int HTTP_VERIFY_CERT = 3; 262 public const int HTTP_VERIFY_CERT = 3;
263 public bool finished; 263 public bool finished;
264 public int httpBodyMaxLen = 2048; // not implemented 264 public int httpBodyMaxLen = 2048; // not implemented
265 265
266 // Parameter members and default values 266 // Parameter members and default values
267 public string httpMethod = "GET"; 267 public string httpMethod = "GET";
268 public string httpMIMEType = "text/plain;charset=utf-8"; 268 public string httpMIMEType = "text/plain;charset=utf-8";
269 private Thread httpThread; 269 private Thread httpThread;
270 public int httpTimeout; 270 public int httpTimeout;
271 public bool httpVerifyCert = true; // not implemented 271 public bool httpVerifyCert = true; // not implemented
272 272
273 // Request info 273 // Request info
274 public LLUUID itemID; 274 public LLUUID itemID;
275 public uint localID; 275 public uint localID;
276 public DateTime next; 276 public DateTime next;
277 public string outbound_body; 277 public string outbound_body;
278 public LLUUID reqID; 278 public LLUUID reqID;
279 public HttpWebRequest request; 279 public HttpWebRequest request;
280 public string response_body; 280 public string response_body;
281 public List<string> response_metadata; 281 public List<string> response_metadata;
282 public int status; 282 public int status;
283 public string url; 283 public string url;
284 284
285 public void process() 285 public void process()
286 { 286 {
287 httpThread = new Thread(SendRequest); 287 httpThread = new Thread(SendRequest);
288 httpThread.Name = "HttpRequestThread"; 288 httpThread.Name = "HttpRequestThread";
289 httpThread.Priority = ThreadPriority.BelowNormal; 289 httpThread.Priority = ThreadPriority.BelowNormal;
290 httpThread.IsBackground = true; 290 httpThread.IsBackground = true;
291 finished = false; 291 finished = false;
292 httpThread.Start(); 292 httpThread.Start();
293 ThreadTracker.Add(httpThread); 293 ThreadTracker.Add(httpThread);
294 } 294 }
295 295
296 /* 296 /*
297 * TODO: More work on the response codes. Right now 297 * TODO: More work on the response codes. Right now
298 * returning 200 for success or 499 for exception 298 * returning 200 for success or 499 for exception
299 */ 299 */
300 300
301 public void SendRequest() 301 public void SendRequest()
302 { 302 {
303 HttpWebResponse response = null; 303 HttpWebResponse response = null;
304 StringBuilder sb = new StringBuilder(); 304 StringBuilder sb = new StringBuilder();
305 byte[] buf = new byte[8192]; 305 byte[] buf = new byte[8192];
306 string tempString = null; 306 string tempString = null;
307 int count = 0; 307 int count = 0;
308 308
309 try 309 try
310 { 310 {
311 request = (HttpWebRequest) 311 request = (HttpWebRequest)
312 WebRequest.Create(url); 312 WebRequest.Create(url);
313 request.Method = httpMethod; 313 request.Method = httpMethod;
314 request.ContentType = httpMIMEType; 314 request.ContentType = httpMIMEType;
315 315
316 request.Timeout = httpTimeout; 316 request.Timeout = httpTimeout;
317 // execute the request 317 // execute the request
318 response = (HttpWebResponse) 318 response = (HttpWebResponse)
319 request.GetResponse(); 319 request.GetResponse();
320 320
321 Stream resStream = response.GetResponseStream(); 321 Stream resStream = response.GetResponseStream();
322 322
323 do 323 do
324 { 324 {
325 // fill the buffer with data 325 // fill the buffer with data
326 count = resStream.Read(buf, 0, buf.Length); 326 count = resStream.Read(buf, 0, buf.Length);
327 327
328 // make sure we read some data 328 // make sure we read some data
329 if (count != 0) 329 if (count != 0)
330 { 330 {
331 // translate from bytes to ASCII text 331 // translate from bytes to ASCII text
332 tempString = Encoding.UTF8.GetString(buf, 0, count); 332 tempString = Encoding.UTF8.GetString(buf, 0, count);
333 333
334 // continue building the string 334 // continue building the string
335 sb.Append(tempString); 335 sb.Append(tempString);
336 } 336 }
337 } while (count > 0); // any more data to read? 337 } while (count > 0); // any more data to read?
338 338
339 response_body = sb.ToString(); 339 response_body = sb.ToString();
340 } 340 }
341 catch (Exception e) 341 catch (Exception e)
342 { 342 {
343 status = 499; 343 status = 499;
344 response_body = e.Message; 344 response_body = e.Message;
345 finished = true; 345 finished = true;
346 return; 346 return;
347 } 347 }
348 348
349 status = 200; 349 status = 200;
350 finished = true; 350 finished = true;
351 } 351 }
352 352
353 public void Stop() 353 public void Stop()
354 { 354 {
355 try 355 try
356 { 356 {
357 httpThread.Abort(); 357 httpThread.Abort();
358 } 358 }
359 catch (Exception) 359 catch (Exception)
360 { 360 {
361 } 361 }
362 } 362 }
363 } 363 }
364} \ No newline at end of file 364} \ No newline at end of file