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