aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/Scripting
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
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')
-rw-r--r--OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs277
-rw-r--r--OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs356
-rw-r--r--OpenSim/Region/Environment/Modules/Scripting/LoadImageURL/LoadImageURLModule.cs179
-rw-r--r--OpenSim/Region/Environment/Modules/Scripting/VectorRender/VectorRenderModule.cs361
-rw-r--r--OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs578
-rw-r--r--OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs672
6 files changed, 2423 insertions, 0 deletions
diff --git a/OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs
new file mode 100644
index 0000000..63eee97
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs
@@ -0,0 +1,277 @@
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.Drawing;
31using System.Drawing.Imaging;
32using libsecondlife;
33using Nini.Config;
34using OpenJPEGNet;
35using OpenSim.Framework;
36using OpenSim.Region.Environment.Interfaces;
37using OpenSim.Region.Environment.Scenes;
38
39namespace OpenSim.Region.Environment.Modules.Scripting.DynamicTexture
40{
41 public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
42 {
43 private Dictionary<LLUUID, Scene> RegisteredScenes = new Dictionary<LLUUID, Scene>();
44
45 private Dictionary<string, IDynamicTextureRender> RenderPlugins =
46 new Dictionary<string, IDynamicTextureRender>();
47
48 private Dictionary<LLUUID, DynamicTextureUpdater> Updaters = new Dictionary<LLUUID, DynamicTextureUpdater>();
49
50 public void Initialise(Scene scene, IConfigSource config)
51 {
52 if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
53 {
54 RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
55 scene.RegisterModuleInterface<IDynamicTextureManager>(this);
56 }
57 }
58
59 public void PostInitialise()
60 {
61 }
62
63 public void Close()
64 {
65 }
66
67 public string Name
68 {
69 get { return "DynamicTextureModule"; }
70 }
71
72 public bool IsSharedModule
73 {
74 get { return true; }
75 }
76
77 public void RegisterRender(string handleType, IDynamicTextureRender render)
78 {
79 if (!RenderPlugins.ContainsKey(handleType))
80 {
81 RenderPlugins.Add(handleType, render);
82 }
83 }
84
85 public void ReturnData(LLUUID id, byte[] data)
86 {
87 if (Updaters.ContainsKey(id))
88 {
89 DynamicTextureUpdater updater = Updaters[id];
90 if (RegisteredScenes.ContainsKey(updater.SimUUID))
91 {
92 Scene scene = RegisteredScenes[updater.SimUUID];
93 updater.DataReceived(data, scene);
94 }
95 }
96 }
97
98
99 public LLUUID AddDynamicTextureURL(LLUUID simID, LLUUID primID, string contentType, string url,
100 string extraParams, int updateTimer)
101 {
102 return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, updateTimer, false, 255);
103 }
104
105 public LLUUID AddDynamicTextureURL(LLUUID simID, LLUUID primID, string contentType, string url,
106 string extraParams, int updateTimer, bool SetBlending, byte AlphaValue)
107 {
108 if (RenderPlugins.ContainsKey(contentType))
109 {
110 //Console.WriteLine("dynamic texture being created: " + url + " of type " + contentType);
111
112 DynamicTextureUpdater updater = new DynamicTextureUpdater();
113 updater.SimUUID = simID;
114 updater.PrimID = primID;
115 updater.ContentType = contentType;
116 updater.Url = url;
117 updater.UpdateTimer = updateTimer;
118 updater.UpdaterID = LLUUID.Random();
119 updater.Params = extraParams;
120 updater.BlendWithOldTexture = SetBlending;
121 updater.FrontAlpha = AlphaValue;
122
123 if (!Updaters.ContainsKey(updater.UpdaterID))
124 {
125 Updaters.Add(updater.UpdaterID, updater);
126 }
127
128 RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams);
129 return updater.UpdaterID;
130 }
131 return LLUUID.Zero;
132 }
133
134 public LLUUID AddDynamicTextureData(LLUUID simID, LLUUID primID, string contentType, string data,
135 string extraParams, int updateTimer)
136 {
137 return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, false, 255);
138 }
139
140 public LLUUID AddDynamicTextureData(LLUUID simID, LLUUID primID, string contentType, string data,
141 string extraParams, int updateTimer, bool SetBlending, byte AlphaValue)
142 {
143 if (RenderPlugins.ContainsKey(contentType))
144 {
145 DynamicTextureUpdater updater = new DynamicTextureUpdater();
146 updater.SimUUID = simID;
147 updater.PrimID = primID;
148 updater.ContentType = contentType;
149 updater.BodyData = data;
150 updater.UpdateTimer = updateTimer;
151 updater.UpdaterID = LLUUID.Random();
152 updater.Params = extraParams;
153 updater.BlendWithOldTexture = SetBlending;
154 updater.FrontAlpha = AlphaValue;
155
156 if (!Updaters.ContainsKey(updater.UpdaterID))
157 {
158 Updaters.Add(updater.UpdaterID, updater);
159 }
160
161 RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
162 return updater.UpdaterID;
163 }
164 return LLUUID.Zero;
165 }
166
167 public class DynamicTextureUpdater
168 {
169 public LLUUID SimUUID;
170 public LLUUID UpdaterID;
171 public string ContentType;
172 public string Url;
173 public string BodyData;
174 public LLUUID PrimID;
175 public int UpdateTimer;
176 public LLUUID LastAssetID;
177 public string Params;
178 public bool BlendWithOldTexture = false;
179 public bool SetNewFrontAlpha = false;
180 public byte FrontAlpha = 255;
181
182 public DynamicTextureUpdater()
183 {
184 LastAssetID = LLUUID.Zero;
185 UpdateTimer = 0;
186 BodyData = null;
187 }
188
189 public void DataReceived(byte[] data, Scene scene)
190 {
191 SceneObjectPart part = scene.GetSceneObjectPart(PrimID);
192 byte[] assetData;
193 AssetBase oldAsset = null;
194 if (BlendWithOldTexture)
195 {
196 LLUUID lastTextureID = part.Shape.Textures.DefaultTexture.TextureID;
197 oldAsset = scene.AssetCache.GetAsset(lastTextureID, true);
198 if (oldAsset != null)
199 {
200 assetData = BlendTextures(data, oldAsset.Data, SetNewFrontAlpha, FrontAlpha);
201 }
202 else
203 {
204 assetData = new byte[data.Length];
205 Array.Copy(data, assetData, data.Length);
206 }
207 }
208 else
209 {
210 assetData = new byte[data.Length];
211 Array.Copy(data, assetData, data.Length);
212 }
213
214 //TODO delete the last asset(data), if it was a dynamic texture
215 AssetBase asset = new AssetBase();
216 asset.FullID = LLUUID.Random();
217 asset.Data = assetData;
218 asset.Name = "DynamicImage" + Util.RandomClass.Next(1, 10000);
219 asset.Type = 0;
220 asset.Description = "dynamic image";
221 asset.Local = false;
222 asset.Temporary = true;
223 scene.AssetCache.AddAsset(asset);
224
225 LastAssetID = asset.FullID;
226
227
228 part.Shape.Textures = new LLObject.TextureEntry(asset.FullID);
229 part.ScheduleFullUpdate();
230 }
231
232// TODO: unused
233// private byte[] BlendTextures(byte[] frontImage, byte[] backImage)
234// {
235// return BlendTextures(frontImage, backImage, false, 0);
236// }
237
238 private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha)
239 {
240 Bitmap image1 = new Bitmap(OpenJPEG.DecodeToImage(frontImage));
241 Bitmap image2 = new Bitmap(OpenJPEG.DecodeToImage(backImage));
242 if (setNewAlpha)
243 {
244 SetAlpha(ref image1, newAlpha);
245 }
246 Bitmap joint = MergeBitMaps(image1, image2);
247
248 return OpenJPEG.EncodeFromImage(joint, true);
249 }
250
251 public Bitmap MergeBitMaps(Bitmap front, Bitmap back)
252 {
253 Bitmap joint;
254 Graphics jG;
255
256 joint = new Bitmap(back.Width, back.Height, PixelFormat.Format32bppArgb);
257 jG = Graphics.FromImage(joint);
258
259 jG.DrawImage(back, 0, 0, back.Width, back.Height);
260 jG.DrawImage(front, 0, 0, back.Width, back.Height);
261
262 return joint;
263 }
264
265 private void SetAlpha(ref Bitmap b, byte alpha)
266 {
267 for (int w = 0; w < b.Width; w++)
268 {
269 for (int h = 0; h < b.Height; h++)
270 {
271 b.SetPixel(w, h, Color.FromArgb(alpha, b.GetPixel(w, h)));
272 }
273 }
274 }
275 }
276 }
277} \ No newline at end of file
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
diff --git a/OpenSim/Region/Environment/Modules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/Environment/Modules/Scripting/LoadImageURL/LoadImageURLModule.cs
new file mode 100644
index 0000000..eaf9d36
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/Scripting/LoadImageURL/LoadImageURLModule.cs
@@ -0,0 +1,179 @@
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.Drawing;
30using System.IO;
31using System.Net;
32using libsecondlife;
33using Nini.Config;
34using OpenJPEGNet;
35using OpenSim.Region.Environment.Interfaces;
36using OpenSim.Region.Environment.Scenes;
37
38namespace OpenSim.Region.Environment.Modules.Scripting.LoadImageURL
39{
40 public class LoadImageURLModule : IRegionModule, IDynamicTextureRender
41 {
42 private string m_name = "LoadImageURL";
43 private IDynamicTextureManager m_textureManager;
44 private Scene m_scene;
45
46 public void Initialise(Scene scene, IConfigSource config)
47 {
48 if (m_scene == null)
49 {
50 m_scene = scene;
51 }
52 }
53
54 public void PostInitialise()
55 {
56 m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>();
57 if (m_textureManager != null)
58 {
59 m_textureManager.RegisterRender(GetContentType(), this);
60 }
61 }
62
63 public void Close()
64 {
65 }
66
67 public string Name
68 {
69 get { return m_name; }
70 }
71
72 public bool IsSharedModule
73 {
74 get { return true; }
75 }
76
77 public string GetName()
78 {
79 return m_name;
80 }
81
82 public string GetContentType()
83 {
84 return ("image");
85 }
86
87 public bool SupportsAsynchronous()
88 {
89 return true;
90 }
91
92 public byte[] ConvertUrl(string url, string extraParams)
93 {
94 return null;
95 }
96
97 public byte[] ConvertStream(Stream data, string extraParams)
98 {
99 return null;
100 }
101
102 public bool AsyncConvertUrl(LLUUID id, string url, string extraParams)
103 {
104 MakeHttpRequest(url, id);
105 return true;
106 }
107
108 public bool AsyncConvertData(LLUUID id, string bodyData, string extraParams)
109 {
110 return false;
111 }
112
113 private void MakeHttpRequest(string url, LLUUID requestID)
114 {
115 WebRequest request = HttpWebRequest.Create(url);
116 RequestState state = new RequestState((HttpWebRequest) request, requestID);
117 IAsyncResult result = request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state);
118
119 TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
120 state.TimeOfRequest = (int) t.TotalSeconds;
121 }
122
123 private void HttpRequestReturn(IAsyncResult result)
124 {
125 RequestState state = (RequestState) result.AsyncState;
126 WebRequest request = (WebRequest) state.Request;
127 HttpWebResponse response = (HttpWebResponse) request.EndGetResponse(result);
128 if (response.StatusCode == HttpStatusCode.OK)
129 {
130 Bitmap image = new Bitmap(response.GetResponseStream());
131 Size newsize;
132
133 // TODO: make this a bit less hard coded
134 if ((image.Height < 64) && (image.Width < 64))
135 {
136 newsize = new Size(32, 32);
137 }
138 else if ((image.Height < 128) && (image.Width < 128))
139 {
140 newsize = new Size(64, 64);
141 }
142 else if ((image.Height <256) && (image.Width < 256))
143 {
144 newsize = new Size(128, 128);
145 }
146 else if ((image.Height < 512 && image.Width < 512))
147 {
148 newsize = new Size(256, 256);
149 }
150 else if ((image.Height < 1024 && image.Width < 1024))
151 {
152 newsize = new Size(512, 512);
153 }
154 else
155 {
156 newsize = new Size(1024,1024);
157 }
158
159 Bitmap resize = new Bitmap(image, newsize);
160 byte[] imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
161
162 m_textureManager.ReturnData(state.RequestID, imageJ2000);
163 }
164 }
165
166 public class RequestState
167 {
168 public HttpWebRequest Request = null;
169 public LLUUID RequestID = LLUUID.Zero;
170 public int TimeOfRequest = 0;
171
172 public RequestState(HttpWebRequest request, LLUUID requestID)
173 {
174 Request = request;
175 RequestID = requestID;
176 }
177 }
178 }
179} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/Environment/Modules/Scripting/VectorRender/VectorRenderModule.cs
new file mode 100644
index 0000000..4fba5b9
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/Scripting/VectorRender/VectorRenderModule.cs
@@ -0,0 +1,361 @@
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.Drawing;
30using System.Drawing.Imaging;
31using System.Globalization;
32using System.IO;
33using System.Net;
34using libsecondlife;
35using Nini.Config;
36using OpenJPEGNet;
37using OpenSim.Region.Environment.Interfaces;
38using OpenSim.Region.Environment.Scenes;
39using Image=System.Drawing.Image;
40
41//using Cairo;
42
43namespace OpenSim.Region.Environment.Modules.Scripting.VectorRender
44{
45 public class VectorRenderModule : IRegionModule, IDynamicTextureRender
46 {
47 private Scene m_scene;
48 private string m_name = "VectorRenderModule";
49 private IDynamicTextureManager m_textureManager;
50
51 public VectorRenderModule()
52 {
53 }
54
55 public void Initialise(Scene scene, IConfigSource config)
56 {
57 if (m_scene == null)
58 {
59 m_scene = scene;
60 }
61 }
62
63 public void PostInitialise()
64 {
65 m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>();
66 if (m_textureManager != null)
67 {
68 m_textureManager.RegisterRender(GetContentType(), this);
69 }
70 }
71
72 public void Close()
73 {
74 }
75
76 public string Name
77 {
78 get { return m_name; }
79 }
80
81 public bool IsSharedModule
82 {
83 get { return true; }
84 }
85
86 private void Draw(string data, LLUUID id, string extraParams)
87 {
88 // TODO: this is a brutal hack. extraParams should actually be parsed reasonably.
89 int size = 256;
90 try {
91 size = Convert.ToInt32(extraParams);
92 } catch (Exception e) {
93
94//Ckrinke: Add a WriteLine to remove the warning about 'e' defined but not used
95 Console.WriteLine("Problem with Draw. Please verify parameters." + e.ToString());
96 }
97
98 if ((size < 128) || (size > 1024))
99 size = 256;
100
101 Bitmap bitmap = new Bitmap(size, size, PixelFormat.Format32bppArgb);
102
103 Graphics graph = Graphics.FromImage(bitmap);
104
105 extraParams = extraParams.ToLower();
106 int alpha = 255;
107 if (extraParams == "setalpha")
108 {
109 alpha = 0;
110 }
111 else
112 {
113 graph.FillRectangle(new SolidBrush(Color.White), 0, 0, size, size);
114 }
115
116 for (int w = 0; w < bitmap.Width; w++)
117 {
118 for (int h = 0; h < bitmap.Height; h++)
119 {
120 bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h)));
121 }
122 }
123
124
125
126 GDIDraw(data, graph);
127
128 byte[] imageJ2000 = OpenJPEG.EncodeFromImage(bitmap, true);
129 m_textureManager.ReturnData(id, imageJ2000);
130
131 }
132
133/*
134 private void CairoDraw(string data, System.Drawing.Graphics graph)
135 {
136 using (Win32Surface draw = new Win32Surface(graph.GetHdc()))
137 {
138 Context contex = new Context(draw);
139
140 contex.Antialias = Antialias.None; //fastest method but low quality
141 contex.LineWidth = 7;
142 char[] lineDelimiter = { ';' };
143 char[] partsDelimiter = { ',' };
144 string[] lines = data.Split(lineDelimiter);
145
146 foreach (string line in lines)
147 {
148 string nextLine = line.Trim();
149
150 if (nextLine.StartsWith("MoveTO"))
151 {
152 float x = 0;
153 float y = 0;
154 GetParams(partsDelimiter, ref nextLine, ref x, ref y);
155 contex.MoveTo(x, y);
156 }
157 else if (nextLine.StartsWith("LineTo"))
158 {
159 float x = 0;
160 float y = 0;
161 GetParams(partsDelimiter, ref nextLine, ref x, ref y);
162 contex.LineTo(x, y);
163 contex.Stroke();
164 }
165 }
166 }
167 graph.ReleaseHdc();
168 }
169*/
170
171 private void GDIDraw(string data, Graphics graph)
172 {
173 Point startPoint = new Point(0, 0);
174 Point endPoint = new Point(0, 0);
175 Pen drawPen = new Pen(Color.Black, 7);
176 Font myFont = new Font("Times New Roman", 14);
177 SolidBrush myBrush = new SolidBrush(Color.Black);
178 char[] lineDelimiter = { ';' };
179 char[] partsDelimiter = { ',' };
180 string[] lines = data.Split(lineDelimiter);
181
182 foreach (string line in lines)
183 {
184 string nextLine = line.Trim();
185 //replace with switch, or even better, do some proper parsing
186 if (nextLine.StartsWith("MoveTo"))
187 {
188 float x = 0;
189 float y = 0;
190 GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y);
191 startPoint.X = (int)x;
192 startPoint.Y = (int)y;
193 }
194 else if (nextLine.StartsWith("LineTo"))
195 {
196 float x = 0;
197 float y = 0;
198 GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y);
199 endPoint.X = (int)x;
200 endPoint.Y = (int)y;
201 graph.DrawLine(drawPen, startPoint, endPoint);
202 startPoint.X = endPoint.X;
203 startPoint.Y = endPoint.Y;
204 }
205 else if (nextLine.StartsWith("Text"))
206 {
207 nextLine = nextLine.Remove(0, 4);
208 nextLine = nextLine.Trim();
209 graph.DrawString(nextLine, myFont, myBrush, startPoint);
210 }
211 else if (nextLine.StartsWith("Image"))
212 {
213 float x = 0;
214 float y = 0;
215 GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y);
216 endPoint.X = (int)x;
217 endPoint.Y = (int)y;
218 Image image = ImageHttpRequest(nextLine);
219 graph.DrawImage(image, (float)startPoint.X, (float)startPoint.Y, x, y);
220 startPoint.X += endPoint.X;
221 startPoint.Y += endPoint.Y;
222 }
223 else if (nextLine.StartsWith("Rectangle"))
224 {
225 float x = 0;
226 float y = 0;
227 GetParams(partsDelimiter, ref nextLine, 9, ref x, ref y);
228 endPoint.X = (int)x;
229 endPoint.Y = (int)y;
230 graph.DrawRectangle(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
231 startPoint.X += endPoint.X;
232 startPoint.Y += endPoint.Y;
233 }
234 else if (nextLine.StartsWith("FillRectangle"))
235 {
236 float x = 0;
237 float y = 0;
238 GetParams(partsDelimiter, ref nextLine, 13, ref x, ref y);
239 endPoint.X = (int)x;
240 endPoint.Y = (int)y;
241 graph.FillRectangle(myBrush, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
242 startPoint.X += endPoint.X;
243 startPoint.Y += endPoint.Y;
244 }
245 else if (nextLine.StartsWith("Ellipse"))
246 {
247 float x = 0;
248 float y = 0;
249 GetParams(partsDelimiter, ref nextLine, 7, ref x, ref y);
250 endPoint.X = (int)x;
251 endPoint.Y = (int)y;
252 graph.DrawEllipse(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
253 startPoint.X += endPoint.X;
254 startPoint.Y += endPoint.Y;
255 }
256 else if (nextLine.StartsWith("FontSize"))
257 {
258 nextLine = nextLine.Remove(0, 8);
259 nextLine = nextLine.Trim();
260 float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture);
261 myFont = new Font("Times New Roman", size);
262 }
263 else if (nextLine.StartsWith("PenSize"))
264 {
265 nextLine = nextLine.Remove(0, 8);
266 nextLine = nextLine.Trim();
267 float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture);
268 drawPen.Width = size;
269 }
270 else if (nextLine.StartsWith("PenColour"))
271 {
272 nextLine = nextLine.Remove(0, 9);
273 nextLine = nextLine.Trim();
274
275 Color newColour = Color.FromName(nextLine);
276
277 myBrush.Color = newColour;
278 drawPen.Color = newColour;
279 }
280 }
281 }
282
283 private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x, ref float y)
284 {
285 line = line.Remove(0, startLength);
286 string[] parts = line.Split(partsDelimiter);
287 if (parts.Length == 2)
288 {
289 string xVal = parts[0].Trim();
290 string yVal = parts[1].Trim();
291 x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture);
292 y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture);
293 }
294 else if (parts.Length > 2)
295 {
296 string xVal = parts[0].Trim();
297 string yVal = parts[1].Trim();
298 x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture);
299 y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture);
300
301 line = "";
302 for (int i = 2; i < parts.Length; i++)
303 {
304 line = line + parts[i].Trim();
305 line = line + " ";
306 }
307 }
308 }
309
310 private Bitmap ImageHttpRequest(string url)
311 {
312 WebRequest request = HttpWebRequest.Create(url);
313//Ckrinke: Comment out for now as 'str' is unused. Bring it back into play later when it is used.
314//Ckrinke Stream str = null;
315 HttpWebResponse response = (HttpWebResponse)(request).GetResponse();
316 if (response.StatusCode == HttpStatusCode.OK)
317 {
318 Bitmap image = new Bitmap(response.GetResponseStream());
319 return image;
320 }
321
322 return null;
323 }
324
325 public string GetContentType()
326 {
327 return ("vector");
328 }
329
330 public string GetName()
331 {
332 return m_name;
333 }
334
335 public bool SupportsAsynchronous()
336 {
337 return true;
338 }
339
340 public byte[] ConvertUrl(string url, string extraParams)
341 {
342 return null;
343 }
344
345 public byte[] ConvertStream(Stream data, string extraParams)
346 {
347 return null;
348 }
349
350 public bool AsyncConvertUrl(LLUUID id, string url, string extraParams)
351 {
352 return false;
353 }
354
355 public bool AsyncConvertData(LLUUID id, string bodyData, string extraParams)
356 {
357 Draw(bodyData, id, extraParams);
358 return true;
359 }
360 }
361} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs
new file mode 100644
index 0000000..a949fb6
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs
@@ -0,0 +1,578 @@
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;
30using libsecondlife;
31using Nini.Config;
32using OpenSim.Framework;
33using OpenSim.Region.Environment.Interfaces;
34using OpenSim.Region.Environment.Scenes;
35
36/*****************************************************
37 *
38 * WorldCommModule
39 *
40 *
41 * Holding place for world comms - basically llListen
42 * function implementation.
43 *
44 * lLListen(integer channel, string name, key id, string msg)
45 * The name, id, and msg arguments specify the filtering
46 * criteria. You can pass the empty string
47 * (or NULL_KEY for id) for these to set a completely
48 * open filter; this causes the listen() event handler to be
49 * invoked for all chat on the channel. To listen only
50 * for chat spoken by a specific object or avatar,
51 * specify the name and/or id arguments. To listen
52 * only for a specific command, specify the
53 * (case-sensitive) msg argument. If msg is not empty,
54 * listener will only hear strings which are exactly equal
55 * to msg. You can also use all the arguments to establish
56 * the most restrictive filtering criteria.
57 *
58 * It might be useful for each listener to maintain a message
59 * digest, with a list of recent messages by UUID. This can
60 * be used to prevent in-world repeater loops. However, the
61 * linden functions do not have this capability, so for now
62 * thats the way it works.
63 *
64 * **************************************************/
65
66namespace OpenSim.Region.Environment.Modules.Scripting.WorldComm
67{
68 public class WorldCommModule : IRegionModule, IWorldComm
69 {
70 private Scene m_scene;
71 private object CommListLock = new object();
72 private object ListLock = new object();
73 private string m_name = "WorldCommModule";
74 private ListenerManager m_listenerManager;
75 private Queue m_pendingQ;
76 private Queue m_pending;
77
78 public WorldCommModule()
79 {
80 }
81
82 public void Initialise(Scene scene, IConfigSource config)
83 {
84 m_scene = scene;
85 m_scene.RegisterModuleInterface<IWorldComm>(this);
86 m_listenerManager = new ListenerManager();
87 m_scene.EventManager.OnNewClient += NewClient;
88 m_pendingQ = new Queue();
89 m_pending = Queue.Synchronized(m_pendingQ);
90 }
91
92 public void PostInitialise()
93 {
94 }
95
96 public void Close()
97 {
98 }
99
100 public string Name
101 {
102 get { return m_name; }
103 }
104
105 public bool IsSharedModule
106 {
107 get { return false; }
108 }
109
110 public void NewClient(IClientAPI client)
111 {
112 client.OnChatFromViewer += DeliverClientMessage;
113 }
114
115 /********************************************************************
116 *
117 * Listener Stuff
118 *
119 * *****************************************************************/
120 private void DeliverClientMessage(Object sender, ChatFromViewerArgs e)
121 {
122 DeliverMessage(e.Sender.AgentId.ToString(),
123 e.Type, e.Channel,
124 e.Sender.FirstName + " " + e.Sender.LastName,
125 e.Message);
126 }
127
128 public int Listen(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg)
129 {
130 return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg);
131 }
132
133 public void ListenControl(int handle, int active)
134 {
135 if (m_listenerManager != null)
136 {
137 if (active == 1)
138 m_listenerManager.Activate(handle);
139 else if (active == 0)
140 m_listenerManager.Dectivate(handle);
141 }
142 }
143
144 public void ListenRemove(int handle)
145 {
146 if (m_listenerManager != null)
147 {
148 m_listenerManager.Remove(handle);
149 }
150 }
151
152 public void DeleteListener(LLUUID itemID)
153 {
154 if (m_listenerManager != null)
155 {
156 m_listenerManager.DeleteListener(itemID);
157 }
158 }
159
160 // This method scans nearby objects and determines if they are listeners,
161 // and if so if this message fits the filter. If it does, then
162 // enqueue the message for delivery to the objects listen event handler.
163 // Objects that do an llSay have their messages delivered here, and for
164 // nearby avatars, the SimChat function is used.
165 public void DeliverMessage(string sourceItemID, ChatTypeEnum type, int channel, string name, string msg)
166 {
167 SceneObjectPart source = null;
168 ScenePresence avatar = null;
169
170 source = m_scene.GetSceneObjectPart(new LLUUID(sourceItemID));
171 if (source == null)
172 {
173 avatar = m_scene.GetScenePresence(new LLUUID(sourceItemID));
174 }
175 if ((avatar != null) || (source != null))
176 {
177 // Loop through the objects in the scene
178 // If they are in proximity, then if they are
179 // listeners, if so add them to the pending queue
180
181 foreach (ListenerInfo li in m_listenerManager.GetListeners())
182 {
183 EntityBase sPart;
184
185 m_scene.Entities.TryGetValue(li.GetHostID(), out sPart);
186
187 if (sPart != null)
188 {
189 double dis = 0;
190
191 if (source != null)
192 dis = Util.GetDistanceTo(sPart.AbsolutePosition, source.AbsolutePosition);
193 else
194 dis = Util.GetDistanceTo(sPart.AbsolutePosition, avatar.AbsolutePosition);
195
196 switch (type)
197 {
198 case ChatTypeEnum.Whisper:
199
200 if ((dis < 10) && (dis > -10))
201 {
202 if (li.GetChannel() == channel)
203 {
204 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
205 sourceItemID, sPart.UUID, channel, name, msg
206 );
207 if (isListener != null)
208 {
209 lock (m_pending.SyncRoot)
210 {
211 m_pending.Enqueue(isListener);
212 }
213 }
214 }
215 }
216 break;
217
218 case ChatTypeEnum.Say:
219
220 if ((dis < 30) && (dis > -30))
221 {
222 if (li.GetChannel() == channel)
223 {
224 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
225 sourceItemID, sPart.UUID, channel, name, msg
226 );
227 if (isListener != null)
228 {
229 lock (m_pending.SyncRoot)
230 {
231 m_pending.Enqueue(isListener);
232 }
233 }
234 }
235 }
236 break;
237
238 case ChatTypeEnum.Shout:
239 if ((dis < 100) && (dis > -100))
240 {
241 if (li.GetChannel() == channel)
242 {
243 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
244 sourceItemID, sPart.UUID, channel, name, msg
245 );
246 if (isListener != null)
247 {
248 lock (m_pending.SyncRoot)
249 {
250 m_pending.Enqueue(isListener);
251 }
252 }
253 }
254 }
255 break;
256
257 case ChatTypeEnum.Broadcast:
258 // Dont process if this message is from itself!
259 if (li.GetHostID().ToString().Equals(sourceItemID) ||
260 sPart.UUID.ToString().Equals(sourceItemID))
261 continue;
262
263 if (li.GetChannel() == channel)
264 {
265 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
266 sourceItemID, sPart.UUID, channel, name, msg
267 );
268 if (isListener != null)
269 {
270 lock (m_pending.SyncRoot)
271 {
272 m_pending.Enqueue(isListener);
273 }
274 }
275 }
276
277 break;
278 }
279 }
280 }
281 }
282 }
283
284 public bool HasMessages()
285 {
286 if (m_pending != null)
287 return (m_pending.Count > 0);
288 else
289 return false;
290 }
291
292 public ListenerInfo GetNextMessage()
293 {
294 ListenerInfo li = null;
295
296 lock (m_pending.SyncRoot)
297 {
298 li = (ListenerInfo)m_pending.Dequeue();
299 }
300
301 return li;
302 }
303
304 public uint PeekNextMessageLocalID()
305 {
306 return ((ListenerInfo)m_pending.Peek()).GetLocalID();
307 }
308
309 public LLUUID PeekNextMessageItemID()
310 {
311 return ((ListenerInfo)m_pending.Peek()).GetItemID();
312 }
313 }
314
315 public class ListenerManager
316 {
317 //private Dictionary<int, ListenerInfo> m_listeners;
318 private Hashtable m_listeners = Hashtable.Synchronized(new Hashtable());
319 private object ListenersLock = new object();
320 private int m_MaxListeners = 100;
321
322 public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg)
323 {
324 if (m_listeners.Count < m_MaxListeners)
325 {
326 ListenerInfo isListener = IsListenerMatch(LLUUID.Zero.ToString(), itemID, channel, name, msg);
327
328 if (isListener == null)
329 {
330 int newHandle = GetNewHandle();
331
332 if (newHandle > -1)
333 {
334 ListenerInfo li = new ListenerInfo(localID, newHandle, itemID, hostID, channel, name, id, msg);
335
336 lock (m_listeners.SyncRoot)
337 {
338 m_listeners.Add(newHandle, li);
339 }
340
341 return newHandle;
342 }
343 }
344 }
345
346 return -1;
347 }
348
349 public void Remove(int handle)
350 {
351 lock (m_listeners.SyncRoot)
352 {
353 m_listeners.Remove(handle);
354 }
355 }
356
357 public void DeleteListener(LLUUID itemID)
358 {
359 ArrayList removedListeners = new ArrayList();
360
361 lock (m_listeners.SyncRoot)
362 {
363 IDictionaryEnumerator en = m_listeners.GetEnumerator();
364 while (en.MoveNext())
365 {
366 ListenerInfo li = (ListenerInfo)en.Value;
367 if (li.GetItemID().Equals(itemID))
368 {
369 removedListeners.Add(li.GetHandle());
370 }
371 }
372 foreach (int handle in removedListeners)
373 {
374 m_listeners.Remove(handle);
375 }
376 }
377 }
378
379 private int GetNewHandle()
380 {
381 for (int i = 0; i < int.MaxValue - 1; i++)
382 {
383 if (!m_listeners.ContainsKey(i))
384 return i;
385 }
386
387 return -1;
388 }
389
390 public bool IsListener(LLUUID hostID)
391 {
392 foreach (ListenerInfo li in m_listeners.Values)
393 {
394 if (li.GetHostID().Equals(hostID))
395 return true;
396 }
397
398 return false;
399 }
400
401 public void Activate(int handle)
402 {
403
404 if (m_listeners.ContainsKey(handle))
405 {
406 lock (m_listeners.SyncRoot)
407 {
408 ListenerInfo li = (ListenerInfo)m_listeners[handle];
409 li.Activate();
410 }
411 }
412 }
413
414 public void Dectivate(int handle)
415 {
416
417 if (m_listeners.ContainsKey(handle))
418 {
419 ListenerInfo li = (ListenerInfo)m_listeners[handle];
420 li.Deactivate();
421 }
422 }
423
424 // Theres probably a more clever and efficient way to
425 // do this, maybe with regex.
426 public ListenerInfo IsListenerMatch(string sourceItemID, LLUUID listenerKey, int channel, string name,
427 string msg)
428 {
429 bool isMatch = true;
430 lock (m_listeners.SyncRoot)
431 {
432 IDictionaryEnumerator en = m_listeners.GetEnumerator();
433 while (en.MoveNext())
434 {
435 ListenerInfo li = (ListenerInfo)en.Value;
436
437 if (li.IsActive())
438 {
439 if (li.GetHostID().Equals(listenerKey))
440 {
441 if (channel == li.GetChannel())
442 {
443 if ((li.GetID().ToString().Length > 0) &&
444 (!li.GetID().Equals(LLUUID.Zero)))
445 {
446 if (!li.GetID().ToString().Equals(sourceItemID))
447 {
448 isMatch = false;
449 }
450 }
451 if (isMatch && (li.GetName().Length > 0))
452 {
453 if (li.GetName().Equals(name))
454 {
455 isMatch = false;
456 }
457 }
458 if (isMatch)
459 {
460 return new ListenerInfo(
461 li.GetLocalID(), li.GetHandle(), li.GetItemID(), li.GetHostID(),
462 li.GetChannel(), name, li.GetID(), msg, new LLUUID(sourceItemID)
463 );
464 }
465 }
466 }
467 }
468 }
469 }
470 return null;
471 }
472
473 public ICollection GetListeners()
474 {
475 return m_listeners.Values;
476 }
477 }
478
479 public class ListenerInfo
480 {
481 private LLUUID m_itemID; // ID of the host script engine
482 private LLUUID m_hostID; // ID of the host/scene part
483 private LLUUID m_sourceItemID; // ID of the scenePart or avatar source of the message
484 private int m_channel; // Channel
485 private int m_handle; // Assigned handle of this listener
486 private uint m_localID; // Local ID from script engine
487 private string m_name; // Object name to filter messages from
488 private LLUUID m_id; // ID to filter messages from
489 private string m_message; // The message
490 private bool m_active; // Listener is active or not
491
492 public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, string message)
493 {
494 Initialise(localID, handle, ItemID, hostID, channel, name, id, message);
495 }
496
497 public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id,
498 string message, LLUUID sourceItemID)
499 {
500 Initialise(localID, handle, ItemID, hostID, channel, name, id, message);
501 m_sourceItemID = sourceItemID;
502 }
503
504 private void Initialise(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name,
505 LLUUID id, string message)
506 {
507 m_handle = handle;
508 m_channel = channel;
509 m_itemID = ItemID;
510 m_hostID = hostID;
511 m_name = name;
512 m_id = id;
513 m_message = message;
514 m_active = true;
515 m_localID = localID;
516 }
517
518 public LLUUID GetItemID()
519 {
520 return m_itemID;
521 }
522
523 public LLUUID GetHostID()
524 {
525 return m_hostID;
526 }
527
528 public LLUUID GetSourceItemID()
529 {
530 return m_sourceItemID;
531 }
532
533 public int GetChannel()
534 {
535 return m_channel;
536 }
537
538 public uint GetLocalID()
539 {
540 return m_localID;
541 }
542
543 public int GetHandle()
544 {
545 return m_handle;
546 }
547
548 public string GetMessage()
549 {
550 return m_message;
551 }
552
553 public string GetName()
554 {
555 return m_name;
556 }
557
558 public bool IsActive()
559 {
560 return m_active;
561 }
562
563 public void Deactivate()
564 {
565 m_active = false;
566 }
567
568 public void Activate()
569 {
570 m_active = true;
571 }
572
573 public LLUUID GetID()
574 {
575 return m_id;
576 }
577 }
578} \ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs
new file mode 100644
index 0000000..1139b4b
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs
@@ -0,0 +1,672 @@
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;
30using System.Collections.Generic;
31using System.Net;
32using System.Reflection;
33using System.Threading;
34using libsecondlife;
35using log4net;
36using Nini.Config;
37using Nwc.XmlRpc;
38using OpenSim.Framework;
39using OpenSim.Framework.Servers;
40using OpenSim.Region.Environment.Interfaces;
41using OpenSim.Region.Environment.Scenes;
42
43/*****************************************************
44 *
45 * XMLRPCModule
46 *
47 * Module for accepting incoming communications from
48 * external XMLRPC client and calling a remote data
49 * procedure for a registered data channel/prim.
50 *
51 *
52 * 1. On module load, open a listener port
53 * 2. Attach an XMLRPC handler
54 * 3. When a request is received:
55 * 3.1 Parse into components: channel key, int, string
56 * 3.2 Look up registered channel listeners
57 * 3.3 Call the channel (prim) remote data method
58 * 3.4 Capture the response (llRemoteDataReply)
59 * 3.5 Return response to client caller
60 * 3.6 If no response from llRemoteDataReply within
61 * RemoteReplyScriptTimeout, generate script timeout fault
62 *
63 * Prims in script must:
64 * 1. Open a remote data channel
65 * 1.1 Generate a channel ID
66 * 1.2 Register primid,channelid pair with module
67 * 2. Implement the remote data procedure handler
68 *
69 * llOpenRemoteDataChannel
70 * llRemoteDataReply
71 * remote_data(integer type, key channel, key messageid, string sender, integer ival, string sval)
72 * llCloseRemoteDataChannel
73 *
74 * **************************************************/
75
76namespace OpenSim.Region.Environment.Modules.Scripting.XMLRPC
77{
78 public class XMLRPCModule : IRegionModule, IXMLRPC
79 {
80 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
81
82 private object XMLRPCListLock = new object();
83 private string m_name = "XMLRPCModule";
84 private int RemoteReplyScriptWait = 300;
85 private int RemoteReplyScriptTimeout = 9000;
86 private int m_remoteDataPort = 0;
87 private List<Scene> m_scenes = new List<Scene>();
88
89 // <channel id, RPCChannelInfo>
90 private Dictionary<LLUUID, RPCChannelInfo> m_openChannels;
91
92 private Dictionary<LLUUID, RPCRequestInfo> m_rpcPending;
93 private Dictionary<LLUUID, RPCRequestInfo> m_rpcPendingResponses;
94
95 private Dictionary<LLUUID, SendRemoteDataRequest> m_pendingSRDResponses;
96
97 public void Initialise(Scene scene, IConfigSource config)
98 {
99 try
100 {
101 m_remoteDataPort = config.Configs["Network"].GetInt("remoteDataPort", m_remoteDataPort);
102 }
103 catch (Exception)
104 {
105 }
106
107 if (!m_scenes.Contains(scene))
108 {
109 m_scenes.Add(scene);
110
111 scene.RegisterModuleInterface<IXMLRPC>(this);
112 }
113 }
114
115 public void PostInitialise()
116 {
117 if (IsEnabled())
118 {
119 m_openChannels = new Dictionary<LLUUID, RPCChannelInfo>();
120 m_rpcPending = new Dictionary<LLUUID, RPCRequestInfo>();
121 m_rpcPendingResponses = new Dictionary<LLUUID, RPCRequestInfo>();
122 m_pendingSRDResponses = new Dictionary<LLUUID, SendRemoteDataRequest>();
123
124 // Start http server
125 // Attach xmlrpc handlers
126 m_log.Info("[REMOTE_DATA]: " +
127 "Starting XMLRPC Server on port " + m_remoteDataPort + " for llRemoteData commands.");
128 BaseHttpServer httpServer = new BaseHttpServer((uint)m_remoteDataPort);
129 httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData);
130 httpServer.Start();
131 }
132 }
133
134 public void Close()
135 {
136 }
137
138 public string Name
139 {
140 get { return m_name; }
141 }
142
143 public bool IsSharedModule
144 {
145 get { return true; }
146 }
147
148 public bool IsEnabled()
149 {
150 return (m_remoteDataPort > 0);
151 }
152
153 /**********************************************
154 * OpenXMLRPCChannel
155 *
156 * Generate a LLUUID channel key and add it and
157 * the prim id to dictionary <channelUUID, primUUID>
158 *
159 * First check if there is a channel assigned for
160 * this itemID. If there is, then someone called
161 * llOpenRemoteDataChannel twice. Just return the
162 * original channel. Other option is to delete the
163 * current channel and assign a new one.
164 *
165 * ********************************************/
166
167 public LLUUID OpenXMLRPCChannel(uint localID, LLUUID itemID)
168 {
169 LLUUID channel = new LLUUID();
170
171 //Is a dupe?
172 foreach (RPCChannelInfo ci in m_openChannels.Values)
173 {
174 if (ci.GetItemID().Equals(itemID))
175 {
176 // return the original channel ID for this item
177 channel = ci.GetChannelID();
178 break;
179 }
180 }
181
182 if (channel == LLUUID.Zero)
183 {
184 channel = LLUUID.Random();
185 RPCChannelInfo rpcChanInfo = new RPCChannelInfo(localID, itemID, channel);
186 lock (XMLRPCListLock)
187 {
188 m_openChannels.Add(channel, rpcChanInfo);
189 }
190 }
191
192 return channel;
193 }
194
195 // Delete channels based on itemID
196 // for when a script is deleted
197 public void DeleteChannels(LLUUID itemID)
198 {
199
200 if (m_openChannels != null)
201 {
202 ArrayList tmp = new ArrayList();
203
204 lock (XMLRPCListLock)
205 {
206 foreach (RPCChannelInfo li in m_openChannels.Values)
207 {
208 if (li.GetItemID().Equals(itemID))
209 {
210 tmp.Add(itemID);
211 }
212 }
213
214 IEnumerator tmpEnumerator = tmp.GetEnumerator();
215 while ( tmpEnumerator.MoveNext() )
216 m_openChannels.Remove((LLUUID)tmpEnumerator.Current);
217 }
218
219 }
220
221 }
222
223 /**********************************************
224 * Remote Data Reply
225 *
226 * Response to RPC message
227 *
228 *********************************************/
229
230 public void RemoteDataReply(string channel, string message_id, string sdata, int idata)
231 {
232 RPCRequestInfo rpcInfo;
233 LLUUID message_key = new LLUUID(message_id);
234
235 if (m_rpcPendingResponses.TryGetValue(message_key, out rpcInfo))
236 {
237 rpcInfo.SetStrRetval(sdata);
238 rpcInfo.SetIntRetval(idata);
239 rpcInfo.SetProcessed(true);
240 m_rpcPendingResponses.Remove(message_key);
241 }
242 }
243
244 /**********************************************
245 * CloseXMLRPCChannel
246 *
247 * Remove channel from dictionary
248 *
249 *********************************************/
250
251 public void CloseXMLRPCChannel(LLUUID channelKey)
252 {
253 if (m_openChannels.ContainsKey(channelKey))
254 m_openChannels.Remove(channelKey);
255 }
256
257
258 public XmlRpcResponse XmlRpcRemoteData(XmlRpcRequest request)
259 {
260 XmlRpcResponse response = new XmlRpcResponse();
261
262 Hashtable requestData = (Hashtable)request.Params[0];
263 bool GoodXML = (requestData.Contains("Channel") && requestData.Contains("IntValue") &&
264 requestData.Contains("StringValue"));
265
266 if (GoodXML)
267 {
268 LLUUID channel = new LLUUID((string)requestData["Channel"]);
269 RPCChannelInfo rpcChanInfo;
270 if (m_openChannels.TryGetValue(channel, out rpcChanInfo))
271 {
272 string intVal = (string)requestData["IntValue"];
273 string strVal = (string)requestData["StringValue"];
274
275 RPCRequestInfo rpcInfo;
276
277 lock (XMLRPCListLock)
278 {
279 rpcInfo =
280 new RPCRequestInfo(rpcChanInfo.GetLocalID(), rpcChanInfo.GetItemID(), channel, strVal,
281 intVal);
282 m_rpcPending.Add(rpcInfo.GetMessageID(), rpcInfo);
283 }
284
285 int timeoutCtr = 0;
286
287 while (!rpcInfo.IsProcessed() && (timeoutCtr < RemoteReplyScriptTimeout))
288 {
289 Thread.Sleep(RemoteReplyScriptWait);
290 timeoutCtr += RemoteReplyScriptWait;
291 }
292 if (rpcInfo.IsProcessed())
293 {
294 Hashtable param = new Hashtable();
295 param["StringValue"] = rpcInfo.GetStrRetval();
296 param["IntValue"] = Convert.ToString(rpcInfo.GetIntRetval());
297
298 ArrayList parameters = new ArrayList();
299 parameters.Add(param);
300
301 response.Value = parameters;
302 rpcInfo = null;
303 }
304 else
305 {
306 response.SetFault(-1, "Script timeout");
307 rpcInfo = null;
308 }
309 }
310 else
311 {
312 response.SetFault(-1, "Invalid channel");
313 }
314 }
315
316 return response;
317 }
318
319 public bool hasRequests()
320 {
321 lock (XMLRPCListLock)
322 {
323 if (m_rpcPending != null)
324 return (m_rpcPending.Count > 0);
325 else
326 return false;
327 }
328 }
329
330 public RPCRequestInfo GetNextCompletedRequest()
331 {
332 if (m_rpcPending != null)
333 {
334 lock (XMLRPCListLock)
335 {
336 foreach (LLUUID luid in m_rpcPending.Keys)
337 {
338 RPCRequestInfo tmpReq;
339
340 if (m_rpcPending.TryGetValue(luid, out tmpReq))
341 {
342
343 if (!tmpReq.IsProcessed()) return tmpReq;
344 }
345 }
346 }
347 }
348 return null;
349 }
350
351 public void RemoveCompletedRequest(LLUUID id)
352 {
353 lock (XMLRPCListLock)
354 {
355 RPCRequestInfo tmp;
356 if (m_rpcPending.TryGetValue(id, out tmp))
357 {
358 m_rpcPending.Remove(id);
359 m_rpcPendingResponses.Add(id, tmp);
360 }
361 else
362 {
363 Console.WriteLine("UNABLE TO REMOVE COMPLETED REQUEST");
364 }
365 }
366 }
367
368 public LLUUID SendRemoteData(uint localID, LLUUID itemID, string channel, string dest, int idata, string sdata)
369 {
370
371 SendRemoteDataRequest req = new SendRemoteDataRequest(
372 localID, itemID, channel, dest, idata, sdata
373 );
374 m_pendingSRDResponses.Add(req.GetReqID(), req);
375 return req.process();
376
377 }
378
379 public SendRemoteDataRequest GetNextCompletedSRDRequest()
380 {
381 if (m_pendingSRDResponses != null)
382 {
383 lock (XMLRPCListLock)
384 {
385 foreach (LLUUID luid in m_pendingSRDResponses.Keys)
386 {
387 SendRemoteDataRequest tmpReq;
388
389 if (m_pendingSRDResponses.TryGetValue(luid, out tmpReq))
390 {
391 if (tmpReq.finished)
392 return tmpReq;
393 }
394 }
395 }
396 }
397 return null;
398 }
399
400 public void RemoveCompletedSRDRequest(LLUUID id)
401 {
402 lock (XMLRPCListLock)
403 {
404 SendRemoteDataRequest tmpReq;
405 if (m_pendingSRDResponses.TryGetValue(id, out tmpReq))
406 {
407 m_pendingSRDResponses.Remove(id);
408 }
409 }
410 }
411
412 public void CancelSRDRequests(LLUUID itemID)
413 {
414 if (m_pendingSRDResponses != null)
415 {
416 lock (XMLRPCListLock)
417 {
418 foreach (SendRemoteDataRequest li in m_pendingSRDResponses.Values)
419 {
420 if (li.m_itemID.Equals(itemID))
421 m_pendingSRDResponses.Remove(li.GetReqID());
422 }
423 }
424 }
425 }
426 }
427
428 public class RPCRequestInfo
429 {
430 private string m_StrVal;
431 private string m_IntVal;
432 private bool m_processed;
433 private string m_respStr;
434 private int m_respInt;
435 private uint m_localID;
436 private LLUUID m_ItemID;
437 private LLUUID m_MessageID;
438 private LLUUID m_ChannelKey;
439
440 public RPCRequestInfo(uint localID, LLUUID itemID, LLUUID channelKey, string strVal, string intVal)
441 {
442 m_localID = localID;
443 m_StrVal = strVal;
444 m_IntVal = intVal;
445 m_ItemID = itemID;
446 m_ChannelKey = channelKey;
447 m_MessageID = LLUUID.Random();
448 m_processed = false;
449 m_respStr = String.Empty;
450 m_respInt = 0;
451 }
452
453 public bool IsProcessed()
454 {
455 return m_processed;
456 }
457
458 public LLUUID GetChannelKey()
459 {
460 return m_ChannelKey;
461 }
462
463 public void SetProcessed(bool processed)
464 {
465 m_processed = processed;
466 }
467
468 public void SetStrRetval(string resp)
469 {
470 m_respStr = resp;
471 }
472
473 public string GetStrRetval()
474 {
475 return m_respStr;
476 }
477 public void SetIntRetval(int resp)
478 {
479 m_respInt = resp;
480 }
481
482 public int GetIntRetval()
483 {
484 return m_respInt;
485 }
486 public uint GetLocalID()
487 {
488 return m_localID;
489 }
490
491 public LLUUID GetItemID()
492 {
493 return m_ItemID;
494 }
495
496 public string GetStrVal()
497 {
498 return m_StrVal;
499 }
500
501 public int GetIntValue()
502 {
503 return int.Parse(m_IntVal);
504 }
505
506 public LLUUID GetMessageID()
507 {
508 return m_MessageID;
509 }
510 }
511
512 public class RPCChannelInfo
513 {
514 private LLUUID m_itemID;
515 private uint m_localID;
516 private LLUUID m_ChannelKey;
517
518 public RPCChannelInfo(uint localID, LLUUID itemID, LLUUID channelID)
519 {
520 m_ChannelKey = channelID;
521 m_localID = localID;
522 m_itemID = itemID;
523 }
524
525 public LLUUID GetItemID()
526 {
527 return m_itemID;
528 }
529
530 public LLUUID GetChannelID()
531 {
532 return m_ChannelKey;
533 }
534
535 public uint GetLocalID()
536 {
537 return m_localID;
538 }
539
540 }
541
542 public class SendRemoteDataRequest
543 {
544
545 public LLUUID reqID;
546 public string destURL;
547 public string channel;
548 public string sdata;
549 public int idata;
550 public bool finished;
551 public string response_sdata;
552 public int response_idata;
553 public XmlRpcRequest request;
554 private Thread httpThread;
555 public LLUUID m_itemID;
556 public uint m_localID;
557 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
558
559 public SendRemoteDataRequest(uint localID, LLUUID itemID, string channel, string dest, int idata, string sdata)
560 {
561
562 this.channel = channel;
563 this.destURL = dest;
564 this.idata = idata;
565 this.sdata = sdata;
566 m_itemID = itemID;
567 m_localID = localID;
568
569 reqID = LLUUID.Random();
570
571 }
572
573 public LLUUID process()
574 {
575 httpThread = new Thread(SendRequest);
576 httpThread.Name = "HttpRequestThread";
577 httpThread.Priority = ThreadPriority.BelowNormal;
578 httpThread.IsBackground = true;
579 finished = false;
580 httpThread.Start();
581 ThreadTracker.Add(httpThread);
582
583 return reqID;
584
585 }
586
587 /*
588 * TODO: More work on the response codes. Right now
589 * returning 200 for success or 499 for exception
590 */
591
592 public void SendRequest()
593 {
594 Hashtable param = new Hashtable();
595
596 // Check if channel is an LLUUID
597 // if not, use as method name
598 LLUUID parseUID;
599 string mName = "llRemoteData";
600 if( (channel != null) && (channel != "") )
601 if( !LLUUID.TryParse(channel, out parseUID) )
602 mName = channel;
603 else
604 param["Channel"] = channel;
605
606 param["StringValue"] = sdata;
607 param["IntValue"] = Convert.ToString(idata);
608
609 ArrayList parameters = new ArrayList();
610 parameters.Add(param);
611 XmlRpcRequest req = new XmlRpcRequest(mName, parameters);
612 try
613 {
614 XmlRpcResponse resp = req.Send(destURL, 30000);
615 if (resp != null)
616 {
617 Hashtable respParms;
618 if(resp.Value.GetType().Equals(Type.GetType("System.Collections.Hashtable"))) {
619 respParms = (Hashtable)resp.Value;
620 }
621 else {
622 ArrayList respData = (ArrayList)resp.Value;
623 respParms = (Hashtable)respData[0];
624 }
625 if (respParms != null)
626 {
627 if (respParms.Contains("StringValue"))
628 {
629 sdata = (string)respParms["StringValue"];
630 }
631 if (respParms.Contains("IntValue"))
632 {
633 idata = Convert.ToInt32((string)respParms["IntValue"]);
634 }
635 if (respParms.Contains("faultString"))
636 {
637 sdata = (string)respParms["faultString"];
638 }
639 if (respParms.Contains("faultCode"))
640 {
641 idata = Convert.ToInt32(respParms["faultCode"]);
642 }
643 }
644 }
645 }
646 catch (WebException we)
647 {
648 sdata = we.Message;
649 m_log.Warn("[SendRemoteDataRequest]: Request failed");
650 m_log.Warn(we.StackTrace);
651 }
652
653 finished = true;
654 }
655
656 public void Stop()
657 {
658 try
659 {
660 httpThread.Abort();
661 }
662 catch (Exception)
663 {
664 }
665 }
666
667 public LLUUID GetReqID()
668 {
669 return reqID;
670 }
671 }
672} \ No newline at end of file