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