aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/Scripting
diff options
context:
space:
mode:
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