From d51ce47b2d7635b17f3dd429158e8f59b78b83aa Mon Sep 17 00:00:00 2001 From: Jeff Ames Date: Thu, 1 May 2008 14:31:30 +0000 Subject: Update svn properties. Minor formatting cleanup. --- .../DynamicTexture/DynamicTextureModule.cs | 564 ++++---- .../Scripting/HttpRequest/ScriptsHttpRequests.cs | 726 +++++------ .../Scripting/LoadImageURL/LoadImageURLModule.cs | 380 +++--- .../Scripting/VectorRender/VectorRenderModule.cs | 736 +++++------ .../Modules/Scripting/WorldComm/WorldCommModule.cs | 1168 ++++++++--------- .../Modules/Scripting/XMLRPC/XMLRPCModule.cs | 1342 ++++++++++---------- 6 files changed, 2458 insertions(+), 2458 deletions(-) (limited to 'OpenSim/Region/Environment/Modules/Scripting') diff --git a/OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs index 68ca5e9..c0e3d3b 100644 --- a/OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ b/OpenSim/Region/Environment/Modules/Scripting/DynamicTexture/DynamicTextureModule.cs @@ -1,283 +1,283 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Imaging; -using libsecondlife; -using Nini.Config; -using OpenJPEGNet; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules.Scripting.DynamicTexture -{ - public class DynamicTextureModule : IRegionModule, IDynamicTextureManager - { - private Dictionary RegisteredScenes = new Dictionary(); - - private Dictionary RenderPlugins = - new Dictionary(); - - private Dictionary Updaters = new Dictionary(); - - #region IDynamicTextureManager Members - - public void RegisterRender(string handleType, IDynamicTextureRender render) - { - if (!RenderPlugins.ContainsKey(handleType)) - { - RenderPlugins.Add(handleType, render); - } - } - - public void ReturnData(LLUUID id, byte[] data) - { - if (Updaters.ContainsKey(id)) - { - DynamicTextureUpdater updater = Updaters[id]; - if (RegisteredScenes.ContainsKey(updater.SimUUID)) - { - Scene scene = RegisteredScenes[updater.SimUUID]; - updater.DataReceived(data, scene); - } - } - } - - - public LLUUID AddDynamicTextureURL(LLUUID simID, LLUUID primID, string contentType, string url, - string extraParams, int updateTimer) - { - return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, updateTimer, false, 255); - } - - public LLUUID AddDynamicTextureURL(LLUUID simID, LLUUID primID, string contentType, string url, - string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) - { - if (RenderPlugins.ContainsKey(contentType)) - { - //Console.WriteLine("dynamic texture being created: " + url + " of type " + contentType); - - DynamicTextureUpdater updater = new DynamicTextureUpdater(); - updater.SimUUID = simID; - updater.PrimID = primID; - updater.ContentType = contentType; - updater.Url = url; - updater.UpdateTimer = updateTimer; - updater.UpdaterID = LLUUID.Random(); - updater.Params = extraParams; - updater.BlendWithOldTexture = SetBlending; - updater.FrontAlpha = AlphaValue; - - if (!Updaters.ContainsKey(updater.UpdaterID)) - { - Updaters.Add(updater.UpdaterID, updater); - } - - RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams); - return updater.UpdaterID; - } - return LLUUID.Zero; - } - - public LLUUID AddDynamicTextureData(LLUUID simID, LLUUID primID, string contentType, string data, - string extraParams, int updateTimer) - { - return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, false, 255); - } - - public LLUUID AddDynamicTextureData(LLUUID simID, LLUUID primID, string contentType, string data, - string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) - { - if (RenderPlugins.ContainsKey(contentType)) - { - DynamicTextureUpdater updater = new DynamicTextureUpdater(); - updater.SimUUID = simID; - updater.PrimID = primID; - updater.ContentType = contentType; - updater.BodyData = data; - updater.UpdateTimer = updateTimer; - updater.UpdaterID = LLUUID.Random(); - updater.Params = extraParams; - updater.BlendWithOldTexture = SetBlending; - updater.FrontAlpha = AlphaValue; - - if (!Updaters.ContainsKey(updater.UpdaterID)) - { - Updaters.Add(updater.UpdaterID, updater); - } - - RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); - return updater.UpdaterID; - } - return LLUUID.Zero; - } - - #endregion - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) - { - RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); - scene.RegisterModuleInterface(this); - } - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "DynamicTextureModule"; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - #region Nested type: DynamicTextureUpdater - - public class DynamicTextureUpdater - { - public bool BlendWithOldTexture = false; - public string BodyData; - public string ContentType; - public byte FrontAlpha = 255; - public LLUUID LastAssetID; - public string Params; - public LLUUID PrimID; - public bool SetNewFrontAlpha = false; - public LLUUID SimUUID; - public LLUUID UpdaterID; - public int UpdateTimer; - public string Url; - - public DynamicTextureUpdater() - { - LastAssetID = LLUUID.Zero; - UpdateTimer = 0; - BodyData = null; - } - - public void DataReceived(byte[] data, Scene scene) - { - SceneObjectPart part = scene.GetSceneObjectPart(PrimID); - byte[] assetData; - AssetBase oldAsset = null; - if (BlendWithOldTexture) - { - LLUUID lastTextureID = part.Shape.Textures.DefaultTexture.TextureID; - oldAsset = scene.AssetCache.GetAsset(lastTextureID, true); - if (oldAsset != null) - { - assetData = BlendTextures(data, oldAsset.Data, SetNewFrontAlpha, FrontAlpha); - } - else - { - assetData = new byte[data.Length]; - Array.Copy(data, assetData, data.Length); - } - } - else - { - assetData = new byte[data.Length]; - Array.Copy(data, assetData, data.Length); - } - - //TODO delete the last asset(data), if it was a dynamic texture - AssetBase asset = new AssetBase(); - asset.FullID = LLUUID.Random(); - asset.Data = assetData; - asset.Name = "DynamicImage" + Util.RandomClass.Next(1, 10000); - asset.Type = 0; - asset.Description = "dynamic image"; - asset.Local = false; - asset.Temporary = true; - scene.AssetCache.AddAsset(asset); - - LastAssetID = asset.FullID; - - - part.Shape.Textures = new LLObject.TextureEntry(asset.FullID); - part.ScheduleFullUpdate(); - } - - private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) - { - Bitmap image1 = new Bitmap(OpenJPEG.DecodeToImage(frontImage)); - Bitmap image2 = new Bitmap(OpenJPEG.DecodeToImage(backImage)); - if (setNewAlpha) - { - SetAlpha(ref image1, newAlpha); - } - Bitmap joint = MergeBitMaps(image1, image2); - - return OpenJPEG.EncodeFromImage(joint, true); - } - - public Bitmap MergeBitMaps(Bitmap front, Bitmap back) - { - Bitmap joint; - Graphics jG; - - joint = new Bitmap(back.Width, back.Height, PixelFormat.Format32bppArgb); - jG = Graphics.FromImage(joint); - - jG.DrawImage(back, 0, 0, back.Width, back.Height); - jG.DrawImage(front, 0, 0, back.Width, back.Height); - - return joint; - } - - private void SetAlpha(ref Bitmap b, byte alpha) - { - for (int w = 0; w < b.Width; w++) - { - for (int h = 0; h < b.Height; h++) - { - b.SetPixel(w, h, Color.FromArgb(alpha, b.GetPixel(w, h))); - } - } - } - } - - #endregion - } +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using libsecondlife; +using Nini.Config; +using OpenJPEGNet; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules.Scripting.DynamicTexture +{ + public class DynamicTextureModule : IRegionModule, IDynamicTextureManager + { + private Dictionary RegisteredScenes = new Dictionary(); + + private Dictionary RenderPlugins = + new Dictionary(); + + private Dictionary Updaters = new Dictionary(); + + #region IDynamicTextureManager Members + + public void RegisterRender(string handleType, IDynamicTextureRender render) + { + if (!RenderPlugins.ContainsKey(handleType)) + { + RenderPlugins.Add(handleType, render); + } + } + + public void ReturnData(LLUUID id, byte[] data) + { + if (Updaters.ContainsKey(id)) + { + DynamicTextureUpdater updater = Updaters[id]; + if (RegisteredScenes.ContainsKey(updater.SimUUID)) + { + Scene scene = RegisteredScenes[updater.SimUUID]; + updater.DataReceived(data, scene); + } + } + } + + + public LLUUID AddDynamicTextureURL(LLUUID simID, LLUUID primID, string contentType, string url, + string extraParams, int updateTimer) + { + return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, updateTimer, false, 255); + } + + public LLUUID AddDynamicTextureURL(LLUUID simID, LLUUID primID, string contentType, string url, + string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) + { + if (RenderPlugins.ContainsKey(contentType)) + { + //Console.WriteLine("dynamic texture being created: " + url + " of type " + contentType); + + DynamicTextureUpdater updater = new DynamicTextureUpdater(); + updater.SimUUID = simID; + updater.PrimID = primID; + updater.ContentType = contentType; + updater.Url = url; + updater.UpdateTimer = updateTimer; + updater.UpdaterID = LLUUID.Random(); + updater.Params = extraParams; + updater.BlendWithOldTexture = SetBlending; + updater.FrontAlpha = AlphaValue; + + if (!Updaters.ContainsKey(updater.UpdaterID)) + { + Updaters.Add(updater.UpdaterID, updater); + } + + RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams); + return updater.UpdaterID; + } + return LLUUID.Zero; + } + + public LLUUID AddDynamicTextureData(LLUUID simID, LLUUID primID, string contentType, string data, + string extraParams, int updateTimer) + { + return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, false, 255); + } + + public LLUUID AddDynamicTextureData(LLUUID simID, LLUUID primID, string contentType, string data, + string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) + { + if (RenderPlugins.ContainsKey(contentType)) + { + DynamicTextureUpdater updater = new DynamicTextureUpdater(); + updater.SimUUID = simID; + updater.PrimID = primID; + updater.ContentType = contentType; + updater.BodyData = data; + updater.UpdateTimer = updateTimer; + updater.UpdaterID = LLUUID.Random(); + updater.Params = extraParams; + updater.BlendWithOldTexture = SetBlending; + updater.FrontAlpha = AlphaValue; + + if (!Updaters.ContainsKey(updater.UpdaterID)) + { + Updaters.Add(updater.UpdaterID, updater); + } + + RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); + return updater.UpdaterID; + } + return LLUUID.Zero; + } + + #endregion + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) + { + RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); + scene.RegisterModuleInterface(this); + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "DynamicTextureModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + #region Nested type: DynamicTextureUpdater + + public class DynamicTextureUpdater + { + public bool BlendWithOldTexture = false; + public string BodyData; + public string ContentType; + public byte FrontAlpha = 255; + public LLUUID LastAssetID; + public string Params; + public LLUUID PrimID; + public bool SetNewFrontAlpha = false; + public LLUUID SimUUID; + public LLUUID UpdaterID; + public int UpdateTimer; + public string Url; + + public DynamicTextureUpdater() + { + LastAssetID = LLUUID.Zero; + UpdateTimer = 0; + BodyData = null; + } + + public void DataReceived(byte[] data, Scene scene) + { + SceneObjectPart part = scene.GetSceneObjectPart(PrimID); + byte[] assetData; + AssetBase oldAsset = null; + if (BlendWithOldTexture) + { + LLUUID lastTextureID = part.Shape.Textures.DefaultTexture.TextureID; + oldAsset = scene.AssetCache.GetAsset(lastTextureID, true); + if (oldAsset != null) + { + assetData = BlendTextures(data, oldAsset.Data, SetNewFrontAlpha, FrontAlpha); + } + else + { + assetData = new byte[data.Length]; + Array.Copy(data, assetData, data.Length); + } + } + else + { + assetData = new byte[data.Length]; + Array.Copy(data, assetData, data.Length); + } + + //TODO delete the last asset(data), if it was a dynamic texture + AssetBase asset = new AssetBase(); + asset.FullID = LLUUID.Random(); + asset.Data = assetData; + asset.Name = "DynamicImage" + Util.RandomClass.Next(1, 10000); + asset.Type = 0; + asset.Description = "dynamic image"; + asset.Local = false; + asset.Temporary = true; + scene.AssetCache.AddAsset(asset); + + LastAssetID = asset.FullID; + + + part.Shape.Textures = new LLObject.TextureEntry(asset.FullID); + part.ScheduleFullUpdate(); + } + + private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) + { + Bitmap image1 = new Bitmap(OpenJPEG.DecodeToImage(frontImage)); + Bitmap image2 = new Bitmap(OpenJPEG.DecodeToImage(backImage)); + if (setNewAlpha) + { + SetAlpha(ref image1, newAlpha); + } + Bitmap joint = MergeBitMaps(image1, image2); + + return OpenJPEG.EncodeFromImage(joint, true); + } + + public Bitmap MergeBitMaps(Bitmap front, Bitmap back) + { + Bitmap joint; + Graphics jG; + + joint = new Bitmap(back.Width, back.Height, PixelFormat.Format32bppArgb); + jG = Graphics.FromImage(joint); + + jG.DrawImage(back, 0, 0, back.Width, back.Height); + jG.DrawImage(front, 0, 0, back.Width, back.Height); + + return joint; + } + + private void SetAlpha(ref Bitmap b, byte alpha) + { + for (int w = 0; w < b.Width; w++) + { + for (int h = 0; h < b.Height; h++) + { + b.SetPixel(w, h, Color.FromArgb(alpha, b.GetPixel(w, h))); + } + } + } + } + + #endregion + } } \ 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 index 184e026..e1339a3 100644 --- a/OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs +++ b/OpenSim/Region/Environment/Modules/Scripting/HttpRequest/ScriptsHttpRequests.cs @@ -1,364 +1,364 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Text; -using System.Threading; -using libsecondlife; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -/***************************************************** - * - * ScriptsHttpRequests - * - * Implements the llHttpRequest and http_response - * callback. - * - * Some stuff was already in LSLLongCmdHandler, and then - * there was this file with a stub class in it. So, - * I am moving some of the objects and functions out of - * LSLLongCmdHandler, such as the HttpRequestClass, the - * start and stop methods, and setting up pending and - * completed queues. These are processed in the - * LSLLongCmdHandler polling loop. Similiar to the - * XMLRPCModule, since that seems to work. - * - * //TODO - * - * This probably needs some throttling mechanism but - * its wide open right now. This applies to both - * number of requests and data volume. - * - * Linden puts all kinds of header fields in the requests. - * Not doing any of that: - * User-Agent - * X-SecondLife-Shard - * X-SecondLife-Object-Name - * X-SecondLife-Object-Key - * X-SecondLife-Region - * X-SecondLife-Local-Position - * X-SecondLife-Local-Velocity - * X-SecondLife-Local-Rotation - * X-SecondLife-Owner-Name - * X-SecondLife-Owner-Key - * - * HTTPS support - * - * Configurable timeout? - * Configurable max repsonse size? - * Configurable - * - * **************************************************/ - -namespace OpenSim.Region.Environment.Modules.Scripting.HttpRequest -{ - public class HttpRequestModule : IRegionModule, IHttpRequests - { - private object HttpListLock = new object(); - private int httpTimeout = 30000; - private string m_name = "HttpScriptRequests"; - - // - private Dictionary m_pendingRequests; - private Scene m_scene; - private Queue rpcQueue = new Queue(); - - public HttpRequestModule() - { - } - - #region IHttpRequests Members - - public LLUUID MakeHttpRequest(string url, string parameters, string body) - { - return LLUUID.Zero; - } - - public LLUUID StartHttpRequest(uint localID, LLUUID itemID, string url, List parameters, string body) - { - LLUUID reqID = LLUUID.Random(); - HttpRequestClass htc = new HttpRequestClass(); - - // Partial implementation: support for parameter flags needed - // see http://wiki.secondlife.com/wiki/LlHTTPRequest - // - // Parameters are expected in {key, value, ... , key, value} - if (parameters != null) - { - string[] parms = parameters.ToArray(); - for (int i = 0; i < parms.Length / 2; i += 2) - { - switch (Int32.Parse(parms[i])) - { - case HttpRequestClass.HTTP_METHOD: - - htc.httpMethod = parms[i + 1]; - break; - - case HttpRequestClass.HTTP_MIMETYPE: - - htc.httpMIMEType = parms[i + 1]; - break; - - case HttpRequestClass.HTTP_BODY_MAXLENGTH: - - // TODO implement me - break; - - case HttpRequestClass.HTTP_VERIFY_CERT: - - // TODO implement me - break; - } - } - } - - htc.localID = localID; - htc.itemID = itemID; - htc.url = url; - htc.reqID = reqID; - htc.httpTimeout = httpTimeout; - htc.outbound_body = body; - - lock (HttpListLock) - { - m_pendingRequests.Add(reqID, htc); - } - - htc.process(); - - return reqID; - } - - public void StopHttpRequest(uint m_localID, LLUUID m_itemID) - { - if (m_pendingRequests != null) - { - lock (HttpListLock) - { - HttpRequestClass tmpReq; - if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq)) - { - tmpReq.Stop(); - m_pendingRequests.Remove(m_itemID); - } - } - } - } - - /* - * TODO - * Not sure how important ordering is is here - the next first - * one completed in the list is returned, based soley on its list - * position, not the order in which the request was started or - * finsihed. I thought about setting up a queue for this, but - * it will need some refactoring and this works 'enough' right now - */ - - public HttpRequestClass GetNextCompletedRequest() - { - lock (HttpListLock) - { - foreach (LLUUID luid in m_pendingRequests.Keys) - { - HttpRequestClass tmpReq; - - if (m_pendingRequests.TryGetValue(luid, out tmpReq)) - { - if (tmpReq.finished) - { - return tmpReq; - } - } - } - } - return null; - } - - public void RemoveCompletedRequest(LLUUID id) - { - lock (HttpListLock) - { - HttpRequestClass tmpReq; - if (m_pendingRequests.TryGetValue(id, out tmpReq)) - { - tmpReq.Stop(); - tmpReq = null; - m_pendingRequests.Remove(id); - } - } - } - - #endregion - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - m_scene = scene; - - m_scene.RegisterModuleInterface(this); - - m_pendingRequests = new Dictionary(); - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return m_name; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - } - - public class HttpRequestClass - { - // Constants for parameters - public const int HTTP_BODY_MAXLENGTH = 2; - public const int HTTP_METHOD = 0; - public const int HTTP_MIMETYPE = 1; - public const int HTTP_VERIFY_CERT = 3; - public bool finished; - public int httpBodyMaxLen = 2048; // not implemented - - // Parameter members and default values - public string httpMethod = "GET"; - public string httpMIMEType = "text/plain;charset=utf-8"; - private Thread httpThread; - public int httpTimeout; - public bool httpVerifyCert = true; // not implemented - - // Request info - public LLUUID itemID; - public uint localID; - public DateTime next; - public string outbound_body; - public LLUUID reqID; - public HttpWebRequest request; - public string response_body; - public List response_metadata; - public int status; - public string url; - - public void process() - { - httpThread = new Thread(SendRequest); - httpThread.Name = "HttpRequestThread"; - httpThread.Priority = ThreadPriority.BelowNormal; - httpThread.IsBackground = true; - finished = false; - httpThread.Start(); - ThreadTracker.Add(httpThread); - } - - /* - * TODO: More work on the response codes. Right now - * returning 200 for success or 499 for exception - */ - - public void SendRequest() - { - HttpWebResponse response = null; - StringBuilder sb = new StringBuilder(); - byte[] buf = new byte[8192]; - string tempString = null; - int count = 0; - - try - { - request = (HttpWebRequest) - WebRequest.Create(url); - request.Method = httpMethod; - request.ContentType = httpMIMEType; - - request.Timeout = httpTimeout; - // execute the request - response = (HttpWebResponse) - request.GetResponse(); - - Stream resStream = response.GetResponseStream(); - - do - { - // fill the buffer with data - count = resStream.Read(buf, 0, buf.Length); - - // make sure we read some data - if (count != 0) - { - // translate from bytes to ASCII text - tempString = Encoding.UTF8.GetString(buf, 0, count); - - // continue building the string - sb.Append(tempString); - } - } while (count > 0); // any more data to read? - - response_body = sb.ToString(); - } - catch (Exception e) - { - status = 499; - response_body = e.Message; - finished = true; - return; - } - - status = 200; - finished = true; - } - - public void Stop() - { - try - { - httpThread.Abort(); - } - catch (Exception) - { - } - } - } +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Text; +using System.Threading; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +/***************************************************** + * + * ScriptsHttpRequests + * + * Implements the llHttpRequest and http_response + * callback. + * + * Some stuff was already in LSLLongCmdHandler, and then + * there was this file with a stub class in it. So, + * I am moving some of the objects and functions out of + * LSLLongCmdHandler, such as the HttpRequestClass, the + * start and stop methods, and setting up pending and + * completed queues. These are processed in the + * LSLLongCmdHandler polling loop. Similiar to the + * XMLRPCModule, since that seems to work. + * + * //TODO + * + * This probably needs some throttling mechanism but + * its wide open right now. This applies to both + * number of requests and data volume. + * + * Linden puts all kinds of header fields in the requests. + * Not doing any of that: + * User-Agent + * X-SecondLife-Shard + * X-SecondLife-Object-Name + * X-SecondLife-Object-Key + * X-SecondLife-Region + * X-SecondLife-Local-Position + * X-SecondLife-Local-Velocity + * X-SecondLife-Local-Rotation + * X-SecondLife-Owner-Name + * X-SecondLife-Owner-Key + * + * HTTPS support + * + * Configurable timeout? + * Configurable max repsonse size? + * Configurable + * + * **************************************************/ + +namespace OpenSim.Region.Environment.Modules.Scripting.HttpRequest +{ + public class HttpRequestModule : IRegionModule, IHttpRequests + { + private object HttpListLock = new object(); + private int httpTimeout = 30000; + private string m_name = "HttpScriptRequests"; + + // + private Dictionary m_pendingRequests; + private Scene m_scene; + private Queue rpcQueue = new Queue(); + + public HttpRequestModule() + { + } + + #region IHttpRequests Members + + public LLUUID MakeHttpRequest(string url, string parameters, string body) + { + return LLUUID.Zero; + } + + public LLUUID StartHttpRequest(uint localID, LLUUID itemID, string url, List parameters, string body) + { + LLUUID reqID = LLUUID.Random(); + HttpRequestClass htc = new HttpRequestClass(); + + // Partial implementation: support for parameter flags needed + // see http://wiki.secondlife.com/wiki/LlHTTPRequest + // + // Parameters are expected in {key, value, ... , key, value} + if (parameters != null) + { + string[] parms = parameters.ToArray(); + for (int i = 0; i < parms.Length / 2; i += 2) + { + switch (Int32.Parse(parms[i])) + { + case HttpRequestClass.HTTP_METHOD: + + htc.httpMethod = parms[i + 1]; + break; + + case HttpRequestClass.HTTP_MIMETYPE: + + htc.httpMIMEType = parms[i + 1]; + break; + + case HttpRequestClass.HTTP_BODY_MAXLENGTH: + + // TODO implement me + break; + + case HttpRequestClass.HTTP_VERIFY_CERT: + + // TODO implement me + break; + } + } + } + + htc.localID = localID; + htc.itemID = itemID; + htc.url = url; + htc.reqID = reqID; + htc.httpTimeout = httpTimeout; + htc.outbound_body = body; + + lock (HttpListLock) + { + m_pendingRequests.Add(reqID, htc); + } + + htc.process(); + + return reqID; + } + + public void StopHttpRequest(uint m_localID, LLUUID m_itemID) + { + if (m_pendingRequests != null) + { + lock (HttpListLock) + { + HttpRequestClass tmpReq; + if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq)) + { + tmpReq.Stop(); + m_pendingRequests.Remove(m_itemID); + } + } + } + } + + /* + * TODO + * Not sure how important ordering is is here - the next first + * one completed in the list is returned, based soley on its list + * position, not the order in which the request was started or + * finsihed. I thought about setting up a queue for this, but + * it will need some refactoring and this works 'enough' right now + */ + + public HttpRequestClass GetNextCompletedRequest() + { + lock (HttpListLock) + { + foreach (LLUUID luid in m_pendingRequests.Keys) + { + HttpRequestClass tmpReq; + + if (m_pendingRequests.TryGetValue(luid, out tmpReq)) + { + if (tmpReq.finished) + { + return tmpReq; + } + } + } + } + return null; + } + + public void RemoveCompletedRequest(LLUUID id) + { + lock (HttpListLock) + { + HttpRequestClass tmpReq; + if (m_pendingRequests.TryGetValue(id, out tmpReq)) + { + tmpReq.Stop(); + tmpReq = null; + m_pendingRequests.Remove(id); + } + } + } + + #endregion + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + + m_scene.RegisterModuleInterface(this); + + m_pendingRequests = new Dictionary(); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return m_name; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + } + + public class HttpRequestClass + { + // Constants for parameters + public const int HTTP_BODY_MAXLENGTH = 2; + public const int HTTP_METHOD = 0; + public const int HTTP_MIMETYPE = 1; + public const int HTTP_VERIFY_CERT = 3; + public bool finished; + public int httpBodyMaxLen = 2048; // not implemented + + // Parameter members and default values + public string httpMethod = "GET"; + public string httpMIMEType = "text/plain;charset=utf-8"; + private Thread httpThread; + public int httpTimeout; + public bool httpVerifyCert = true; // not implemented + + // Request info + public LLUUID itemID; + public uint localID; + public DateTime next; + public string outbound_body; + public LLUUID reqID; + public HttpWebRequest request; + public string response_body; + public List response_metadata; + public int status; + public string url; + + public void process() + { + httpThread = new Thread(SendRequest); + httpThread.Name = "HttpRequestThread"; + httpThread.Priority = ThreadPriority.BelowNormal; + httpThread.IsBackground = true; + finished = false; + httpThread.Start(); + ThreadTracker.Add(httpThread); + } + + /* + * TODO: More work on the response codes. Right now + * returning 200 for success or 499 for exception + */ + + public void SendRequest() + { + HttpWebResponse response = null; + StringBuilder sb = new StringBuilder(); + byte[] buf = new byte[8192]; + string tempString = null; + int count = 0; + + try + { + request = (HttpWebRequest) + WebRequest.Create(url); + request.Method = httpMethod; + request.ContentType = httpMIMEType; + + request.Timeout = httpTimeout; + // execute the request + response = (HttpWebResponse) + request.GetResponse(); + + Stream resStream = response.GetResponseStream(); + + do + { + // fill the buffer with data + count = resStream.Read(buf, 0, buf.Length); + + // make sure we read some data + if (count != 0) + { + // translate from bytes to ASCII text + tempString = Encoding.UTF8.GetString(buf, 0, count); + + // continue building the string + sb.Append(tempString); + } + } while (count > 0); // any more data to read? + + response_body = sb.ToString(); + } + catch (Exception e) + { + status = 499; + response_body = e.Message; + finished = true; + return; + } + + status = 200; + finished = true; + } + + public void Stop() + { + try + { + httpThread.Abort(); + } + catch (Exception) + { + } + } + } } \ 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 index a0408cd..c828ef0 100644 --- a/OpenSim/Region/Environment/Modules/Scripting/LoadImageURL/LoadImageURLModule.cs +++ b/OpenSim/Region/Environment/Modules/Scripting/LoadImageURL/LoadImageURLModule.cs @@ -1,191 +1,191 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Drawing; -using System.IO; -using System.Net; -using libsecondlife; -using Nini.Config; -using OpenJPEGNet; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules.Scripting.LoadImageURL -{ - public class LoadImageURLModule : IRegionModule, IDynamicTextureRender - { - private string m_name = "LoadImageURL"; - private Scene m_scene; - private IDynamicTextureManager m_textureManager; - - #region IDynamicTextureRender Members - - public string GetName() - { - return m_name; - } - - public string GetContentType() - { - return ("image"); - } - - public bool SupportsAsynchronous() - { - return true; - } - - public byte[] ConvertUrl(string url, string extraParams) - { - return null; - } - - public byte[] ConvertStream(Stream data, string extraParams) - { - return null; - } - - public bool AsyncConvertUrl(LLUUID id, string url, string extraParams) - { - MakeHttpRequest(url, id); - return true; - } - - public bool AsyncConvertData(LLUUID id, string bodyData, string extraParams) - { - return false; - } - - #endregion - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - if (m_scene == null) - { - m_scene = scene; - } - } - - public void PostInitialise() - { - m_textureManager = m_scene.RequestModuleInterface(); - if (m_textureManager != null) - { - m_textureManager.RegisterRender(GetContentType(), this); - } - } - - public void Close() - { - } - - public string Name - { - get { return m_name; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - private void MakeHttpRequest(string url, LLUUID requestID) - { - WebRequest request = HttpWebRequest.Create(url); - RequestState state = new RequestState((HttpWebRequest) request, requestID); - IAsyncResult result = request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state); - - TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1)); - state.TimeOfRequest = (int) t.TotalSeconds; - } - - private void HttpRequestReturn(IAsyncResult result) - { - RequestState state = (RequestState) result.AsyncState; - WebRequest request = (WebRequest) state.Request; - HttpWebResponse response = (HttpWebResponse) request.EndGetResponse(result); - if (response.StatusCode == HttpStatusCode.OK) - { - Bitmap image = new Bitmap(response.GetResponseStream()); - Size newsize; - - // TODO: make this a bit less hard coded - if ((image.Height < 64) && (image.Width < 64)) - { - newsize = new Size(32, 32); - } - else if ((image.Height < 128) && (image.Width < 128)) - { - newsize = new Size(64, 64); - } - else if ((image.Height < 256) && (image.Width < 256)) - { - newsize = new Size(128, 128); - } - else if ((image.Height < 512 && image.Width < 512)) - { - newsize = new Size(256, 256); - } - else if ((image.Height < 1024 && image.Width < 1024)) - { - newsize = new Size(512, 512); - } - else - { - newsize = new Size(1024, 1024); - } - - Bitmap resize = new Bitmap(image, newsize); - byte[] imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); - - m_textureManager.ReturnData(state.RequestID, imageJ2000); - } - } - - #region Nested type: RequestState - - public class RequestState - { - public HttpWebRequest Request = null; - public LLUUID RequestID = LLUUID.Zero; - public int TimeOfRequest = 0; - - public RequestState(HttpWebRequest request, LLUUID requestID) - { - Request = request; - RequestID = requestID; - } - } - - #endregion - } +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Drawing; +using System.IO; +using System.Net; +using libsecondlife; +using Nini.Config; +using OpenJPEGNet; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules.Scripting.LoadImageURL +{ + public class LoadImageURLModule : IRegionModule, IDynamicTextureRender + { + private string m_name = "LoadImageURL"; + private Scene m_scene; + private IDynamicTextureManager m_textureManager; + + #region IDynamicTextureRender Members + + public string GetName() + { + return m_name; + } + + public string GetContentType() + { + return ("image"); + } + + public bool SupportsAsynchronous() + { + return true; + } + + public byte[] ConvertUrl(string url, string extraParams) + { + return null; + } + + public byte[] ConvertStream(Stream data, string extraParams) + { + return null; + } + + public bool AsyncConvertUrl(LLUUID id, string url, string extraParams) + { + MakeHttpRequest(url, id); + return true; + } + + public bool AsyncConvertData(LLUUID id, string bodyData, string extraParams) + { + return false; + } + + #endregion + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + if (m_scene == null) + { + m_scene = scene; + } + } + + public void PostInitialise() + { + m_textureManager = m_scene.RequestModuleInterface(); + if (m_textureManager != null) + { + m_textureManager.RegisterRender(GetContentType(), this); + } + } + + public void Close() + { + } + + public string Name + { + get { return m_name; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + private void MakeHttpRequest(string url, LLUUID requestID) + { + WebRequest request = HttpWebRequest.Create(url); + RequestState state = new RequestState((HttpWebRequest) request, requestID); + IAsyncResult result = request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state); + + TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1)); + state.TimeOfRequest = (int) t.TotalSeconds; + } + + private void HttpRequestReturn(IAsyncResult result) + { + RequestState state = (RequestState) result.AsyncState; + WebRequest request = (WebRequest) state.Request; + HttpWebResponse response = (HttpWebResponse) request.EndGetResponse(result); + if (response.StatusCode == HttpStatusCode.OK) + { + Bitmap image = new Bitmap(response.GetResponseStream()); + Size newsize; + + // TODO: make this a bit less hard coded + if ((image.Height < 64) && (image.Width < 64)) + { + newsize = new Size(32, 32); + } + else if ((image.Height < 128) && (image.Width < 128)) + { + newsize = new Size(64, 64); + } + else if ((image.Height < 256) && (image.Width < 256)) + { + newsize = new Size(128, 128); + } + else if ((image.Height < 512 && image.Width < 512)) + { + newsize = new Size(256, 256); + } + else if ((image.Height < 1024 && image.Width < 1024)) + { + newsize = new Size(512, 512); + } + else + { + newsize = new Size(1024, 1024); + } + + Bitmap resize = new Bitmap(image, newsize); + byte[] imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); + + m_textureManager.ReturnData(state.RequestID, imageJ2000); + } + } + + #region Nested type: RequestState + + public class RequestState + { + public HttpWebRequest Request = null; + public LLUUID RequestID = LLUUID.Zero; + public int TimeOfRequest = 0; + + public RequestState(HttpWebRequest request, LLUUID requestID) + { + Request = request; + RequestID = requestID; + } + } + + #endregion + } } \ 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 index 386c2b5..626c60f 100644 --- a/OpenSim/Region/Environment/Modules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/Environment/Modules/Scripting/VectorRender/VectorRenderModule.cs @@ -1,369 +1,369 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Drawing; -using System.Drawing.Imaging; -using System.Globalization; -using System.IO; -using System.Net; -using libsecondlife; -using Nini.Config; -using OpenJPEGNet; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; -using Image=System.Drawing.Image; - -//using Cairo; - -namespace OpenSim.Region.Environment.Modules.Scripting.VectorRender -{ - public class VectorRenderModule : IRegionModule, IDynamicTextureRender - { - private string m_name = "VectorRenderModule"; - private Scene m_scene; - private IDynamicTextureManager m_textureManager; - - public VectorRenderModule() - { - } - - #region IDynamicTextureRender Members - - public string GetContentType() - { - return ("vector"); - } - - public string GetName() - { - return m_name; - } - - public bool SupportsAsynchronous() - { - return true; - } - - public byte[] ConvertUrl(string url, string extraParams) - { - return null; - } - - public byte[] ConvertStream(Stream data, string extraParams) - { - return null; - } - - public bool AsyncConvertUrl(LLUUID id, string url, string extraParams) - { - return false; - } - - public bool AsyncConvertData(LLUUID id, string bodyData, string extraParams) - { - Draw(bodyData, id, extraParams); - return true; - } - - #endregion - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - if (m_scene == null) - { - m_scene = scene; - } - } - - public void PostInitialise() - { - m_textureManager = m_scene.RequestModuleInterface(); - if (m_textureManager != null) - { - m_textureManager.RegisterRender(GetContentType(), this); - } - } - - public void Close() - { - } - - public string Name - { - get { return m_name; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - private void Draw(string data, LLUUID id, string extraParams) - { - // TODO: this is a brutal hack. extraParams should actually be parsed reasonably. - int size = 256; - try - { - size = Convert.ToInt32(extraParams); - } - catch (Exception e) - { -//Ckrinke: Add a WriteLine to remove the warning about 'e' defined but not used - Console.WriteLine("Problem with Draw. Please verify parameters." + e.ToString()); - } - - if ((size < 128) || (size > 1024)) - size = 256; - - Bitmap bitmap = new Bitmap(size, size, PixelFormat.Format32bppArgb); - - Graphics graph = Graphics.FromImage(bitmap); - - extraParams = extraParams.ToLower(); - int alpha = 255; - if (extraParams == "setalpha") - { - alpha = 0; - } - else - { - graph.FillRectangle(new SolidBrush(Color.White), 0, 0, size, size); - } - - for (int w = 0; w < bitmap.Width; w++) - { - for (int h = 0; h < bitmap.Height; h++) - { - bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); - } - } - - - GDIDraw(data, graph); - - byte[] imageJ2000 = OpenJPEG.EncodeFromImage(bitmap, true); - m_textureManager.ReturnData(id, imageJ2000); - } - -/* - private void CairoDraw(string data, System.Drawing.Graphics graph) - { - using (Win32Surface draw = new Win32Surface(graph.GetHdc())) - { - Context contex = new Context(draw); - - contex.Antialias = Antialias.None; //fastest method but low quality - contex.LineWidth = 7; - char[] lineDelimiter = { ';' }; - char[] partsDelimiter = { ',' }; - string[] lines = data.Split(lineDelimiter); - - foreach (string line in lines) - { - string nextLine = line.Trim(); - - if (nextLine.StartsWith("MoveTO")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, ref x, ref y); - contex.MoveTo(x, y); - } - else if (nextLine.StartsWith("LineTo")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, ref x, ref y); - contex.LineTo(x, y); - contex.Stroke(); - } - } - } - graph.ReleaseHdc(); - } -*/ - - private void GDIDraw(string data, Graphics graph) - { - Point startPoint = new Point(0, 0); - Point endPoint = new Point(0, 0); - Pen drawPen = new Pen(Color.Black, 7); - Font myFont = new Font("Times New Roman", 14); - SolidBrush myBrush = new SolidBrush(Color.Black); - char[] lineDelimiter = {';'}; - char[] partsDelimiter = {','}; - string[] lines = data.Split(lineDelimiter); - - foreach (string line in lines) - { - string nextLine = line.Trim(); - //replace with switch, or even better, do some proper parsing - if (nextLine.StartsWith("MoveTo")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y); - startPoint.X = (int) x; - startPoint.Y = (int) y; - } - else if (nextLine.StartsWith("LineTo")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y); - endPoint.X = (int) x; - endPoint.Y = (int) y; - graph.DrawLine(drawPen, startPoint, endPoint); - startPoint.X = endPoint.X; - startPoint.Y = endPoint.Y; - } - else if (nextLine.StartsWith("Text")) - { - nextLine = nextLine.Remove(0, 4); - nextLine = nextLine.Trim(); - graph.DrawString(nextLine, myFont, myBrush, startPoint); - } - else if (nextLine.StartsWith("Image")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); - endPoint.X = (int) x; - endPoint.Y = (int) y; - Image image = ImageHttpRequest(nextLine); - graph.DrawImage(image, (float) startPoint.X, (float) startPoint.Y, x, y); - startPoint.X += endPoint.X; - startPoint.Y += endPoint.Y; - } - else if (nextLine.StartsWith("Rectangle")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, 9, ref x, ref y); - endPoint.X = (int) x; - endPoint.Y = (int) y; - graph.DrawRectangle(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); - startPoint.X += endPoint.X; - startPoint.Y += endPoint.Y; - } - else if (nextLine.StartsWith("FillRectangle")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, 13, ref x, ref y); - endPoint.X = (int) x; - endPoint.Y = (int) y; - graph.FillRectangle(myBrush, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); - startPoint.X += endPoint.X; - startPoint.Y += endPoint.Y; - } - else if (nextLine.StartsWith("Ellipse")) - { - float x = 0; - float y = 0; - GetParams(partsDelimiter, ref nextLine, 7, ref x, ref y); - endPoint.X = (int) x; - endPoint.Y = (int) y; - graph.DrawEllipse(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); - startPoint.X += endPoint.X; - startPoint.Y += endPoint.Y; - } - else if (nextLine.StartsWith("FontSize")) - { - nextLine = nextLine.Remove(0, 8); - nextLine = nextLine.Trim(); - float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture); - myFont = new Font("Times New Roman", size); - } - else if (nextLine.StartsWith("PenSize")) - { - nextLine = nextLine.Remove(0, 8); - nextLine = nextLine.Trim(); - float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture); - drawPen.Width = size; - } - else if (nextLine.StartsWith("PenColour")) - { - nextLine = nextLine.Remove(0, 9); - nextLine = nextLine.Trim(); - - Color newColour = Color.FromName(nextLine); - - myBrush.Color = newColour; - drawPen.Color = newColour; - } - } - } - - private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x, ref float y) - { - line = line.Remove(0, startLength); - string[] parts = line.Split(partsDelimiter); - if (parts.Length == 2) - { - string xVal = parts[0].Trim(); - string yVal = parts[1].Trim(); - x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture); - y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture); - } - else if (parts.Length > 2) - { - string xVal = parts[0].Trim(); - string yVal = parts[1].Trim(); - x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture); - y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture); - - line = ""; - for (int i = 2; i < parts.Length; i++) - { - line = line + parts[i].Trim(); - line = line + " "; - } - } - } - - private Bitmap ImageHttpRequest(string url) - { - WebRequest request = HttpWebRequest.Create(url); -//Ckrinke: Comment out for now as 'str' is unused. Bring it back into play later when it is used. -//Ckrinke Stream str = null; - HttpWebResponse response = (HttpWebResponse) (request).GetResponse(); - if (response.StatusCode == HttpStatusCode.OK) - { - Bitmap image = new Bitmap(response.GetResponseStream()); - return image; - } - - return null; - } - } +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.Globalization; +using System.IO; +using System.Net; +using libsecondlife; +using Nini.Config; +using OpenJPEGNet; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; +using Image=System.Drawing.Image; + +//using Cairo; + +namespace OpenSim.Region.Environment.Modules.Scripting.VectorRender +{ + public class VectorRenderModule : IRegionModule, IDynamicTextureRender + { + private string m_name = "VectorRenderModule"; + private Scene m_scene; + private IDynamicTextureManager m_textureManager; + + public VectorRenderModule() + { + } + + #region IDynamicTextureRender Members + + public string GetContentType() + { + return ("vector"); + } + + public string GetName() + { + return m_name; + } + + public bool SupportsAsynchronous() + { + return true; + } + + public byte[] ConvertUrl(string url, string extraParams) + { + return null; + } + + public byte[] ConvertStream(Stream data, string extraParams) + { + return null; + } + + public bool AsyncConvertUrl(LLUUID id, string url, string extraParams) + { + return false; + } + + public bool AsyncConvertData(LLUUID id, string bodyData, string extraParams) + { + Draw(bodyData, id, extraParams); + return true; + } + + #endregion + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + if (m_scene == null) + { + m_scene = scene; + } + } + + public void PostInitialise() + { + m_textureManager = m_scene.RequestModuleInterface(); + if (m_textureManager != null) + { + m_textureManager.RegisterRender(GetContentType(), this); + } + } + + public void Close() + { + } + + public string Name + { + get { return m_name; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + private void Draw(string data, LLUUID id, string extraParams) + { + // TODO: this is a brutal hack. extraParams should actually be parsed reasonably. + int size = 256; + try + { + size = Convert.ToInt32(extraParams); + } + catch (Exception e) + { +//Ckrinke: Add a WriteLine to remove the warning about 'e' defined but not used + Console.WriteLine("Problem with Draw. Please verify parameters." + e.ToString()); + } + + if ((size < 128) || (size > 1024)) + size = 256; + + Bitmap bitmap = new Bitmap(size, size, PixelFormat.Format32bppArgb); + + Graphics graph = Graphics.FromImage(bitmap); + + extraParams = extraParams.ToLower(); + int alpha = 255; + if (extraParams == "setalpha") + { + alpha = 0; + } + else + { + graph.FillRectangle(new SolidBrush(Color.White), 0, 0, size, size); + } + + for (int w = 0; w < bitmap.Width; w++) + { + for (int h = 0; h < bitmap.Height; h++) + { + bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); + } + } + + + GDIDraw(data, graph); + + byte[] imageJ2000 = OpenJPEG.EncodeFromImage(bitmap, true); + m_textureManager.ReturnData(id, imageJ2000); + } + +/* + private void CairoDraw(string data, System.Drawing.Graphics graph) + { + using (Win32Surface draw = new Win32Surface(graph.GetHdc())) + { + Context contex = new Context(draw); + + contex.Antialias = Antialias.None; //fastest method but low quality + contex.LineWidth = 7; + char[] lineDelimiter = { ';' }; + char[] partsDelimiter = { ',' }; + string[] lines = data.Split(lineDelimiter); + + foreach (string line in lines) + { + string nextLine = line.Trim(); + + if (nextLine.StartsWith("MoveTO")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, ref x, ref y); + contex.MoveTo(x, y); + } + else if (nextLine.StartsWith("LineTo")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, ref x, ref y); + contex.LineTo(x, y); + contex.Stroke(); + } + } + } + graph.ReleaseHdc(); + } +*/ + + private void GDIDraw(string data, Graphics graph) + { + Point startPoint = new Point(0, 0); + Point endPoint = new Point(0, 0); + Pen drawPen = new Pen(Color.Black, 7); + Font myFont = new Font("Times New Roman", 14); + SolidBrush myBrush = new SolidBrush(Color.Black); + char[] lineDelimiter = {';'}; + char[] partsDelimiter = {','}; + string[] lines = data.Split(lineDelimiter); + + foreach (string line in lines) + { + string nextLine = line.Trim(); + //replace with switch, or even better, do some proper parsing + if (nextLine.StartsWith("MoveTo")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y); + startPoint.X = (int) x; + startPoint.Y = (int) y; + } + else if (nextLine.StartsWith("LineTo")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 6, ref x, ref y); + endPoint.X = (int) x; + endPoint.Y = (int) y; + graph.DrawLine(drawPen, startPoint, endPoint); + startPoint.X = endPoint.X; + startPoint.Y = endPoint.Y; + } + else if (nextLine.StartsWith("Text")) + { + nextLine = nextLine.Remove(0, 4); + nextLine = nextLine.Trim(); + graph.DrawString(nextLine, myFont, myBrush, startPoint); + } + else if (nextLine.StartsWith("Image")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); + endPoint.X = (int) x; + endPoint.Y = (int) y; + Image image = ImageHttpRequest(nextLine); + graph.DrawImage(image, (float) startPoint.X, (float) startPoint.Y, x, y); + startPoint.X += endPoint.X; + startPoint.Y += endPoint.Y; + } + else if (nextLine.StartsWith("Rectangle")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 9, ref x, ref y); + endPoint.X = (int) x; + endPoint.Y = (int) y; + graph.DrawRectangle(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); + startPoint.X += endPoint.X; + startPoint.Y += endPoint.Y; + } + else if (nextLine.StartsWith("FillRectangle")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 13, ref x, ref y); + endPoint.X = (int) x; + endPoint.Y = (int) y; + graph.FillRectangle(myBrush, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); + startPoint.X += endPoint.X; + startPoint.Y += endPoint.Y; + } + else if (nextLine.StartsWith("Ellipse")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 7, ref x, ref y); + endPoint.X = (int) x; + endPoint.Y = (int) y; + graph.DrawEllipse(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); + startPoint.X += endPoint.X; + startPoint.Y += endPoint.Y; + } + else if (nextLine.StartsWith("FontSize")) + { + nextLine = nextLine.Remove(0, 8); + nextLine = nextLine.Trim(); + float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture); + myFont = new Font("Times New Roman", size); + } + else if (nextLine.StartsWith("PenSize")) + { + nextLine = nextLine.Remove(0, 8); + nextLine = nextLine.Trim(); + float size = Convert.ToSingle(nextLine, CultureInfo.InvariantCulture); + drawPen.Width = size; + } + else if (nextLine.StartsWith("PenColour")) + { + nextLine = nextLine.Remove(0, 9); + nextLine = nextLine.Trim(); + + Color newColour = Color.FromName(nextLine); + + myBrush.Color = newColour; + drawPen.Color = newColour; + } + } + } + + private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x, ref float y) + { + line = line.Remove(0, startLength); + string[] parts = line.Split(partsDelimiter); + if (parts.Length == 2) + { + string xVal = parts[0].Trim(); + string yVal = parts[1].Trim(); + x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture); + y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture); + } + else if (parts.Length > 2) + { + string xVal = parts[0].Trim(); + string yVal = parts[1].Trim(); + x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture); + y = Convert.ToSingle(yVal, CultureInfo.InvariantCulture); + + line = ""; + for (int i = 2; i < parts.Length; i++) + { + line = line + parts[i].Trim(); + line = line + " "; + } + } + } + + private Bitmap ImageHttpRequest(string url) + { + WebRequest request = HttpWebRequest.Create(url); +//Ckrinke: Comment out for now as 'str' is unused. Bring it back into play later when it is used. +//Ckrinke Stream str = null; + HttpWebResponse response = (HttpWebResponse) (request).GetResponse(); + if (response.StatusCode == HttpStatusCode.OK) + { + Bitmap image = new Bitmap(response.GetResponseStream()); + return image; + } + + return null; + } + } } \ 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 index ff3b31e..e79b2bd 100644 --- a/OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs +++ b/OpenSim/Region/Environment/Modules/Scripting/WorldComm/WorldCommModule.cs @@ -1,585 +1,585 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using libsecondlife; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -/***************************************************** - * - * WorldCommModule - * - * - * Holding place for world comms - basically llListen - * function implementation. - * - * lLListen(integer channel, string name, key id, string msg) - * The name, id, and msg arguments specify the filtering - * criteria. You can pass the empty string - * (or NULL_KEY for id) for these to set a completely - * open filter; this causes the listen() event handler to be - * invoked for all chat on the channel. To listen only - * for chat spoken by a specific object or avatar, - * specify the name and/or id arguments. To listen - * only for a specific command, specify the - * (case-sensitive) msg argument. If msg is not empty, - * listener will only hear strings which are exactly equal - * to msg. You can also use all the arguments to establish - * the most restrictive filtering criteria. - * - * It might be useful for each listener to maintain a message - * digest, with a list of recent messages by UUID. This can - * be used to prevent in-world repeater loops. However, the - * linden functions do not have this capability, so for now - * thats the way it works. - * - * **************************************************/ - -namespace OpenSim.Region.Environment.Modules.Scripting.WorldComm -{ - public class WorldCommModule : IRegionModule, IWorldComm - { - private object CommListLock = new object(); - private object ListLock = new object(); - private ListenerManager m_listenerManager; - private string m_name = "WorldCommModule"; - private Queue m_pending; - private Queue m_pendingQ; - private Scene m_scene; - - public WorldCommModule() - { - } - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - m_scene = scene; - m_scene.RegisterModuleInterface(this); - m_listenerManager = new ListenerManager(); - m_scene.EventManager.OnNewClient += NewClient; - m_pendingQ = new Queue(); - m_pending = Queue.Synchronized(m_pendingQ); - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return m_name; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - - #region IWorldComm Members - - public int Listen(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg) - { - return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg); - } - - public void ListenControl(int handle, int active) - { - if (m_listenerManager != null) - { - if (active == 1) - m_listenerManager.Activate(handle); - else if (active == 0) - m_listenerManager.Dectivate(handle); - } - } - - public void ListenRemove(int handle) - { - if (m_listenerManager != null) - { - m_listenerManager.Remove(handle); - } - } - - public void DeleteListener(LLUUID itemID) - { - if (m_listenerManager != null) - { - m_listenerManager.DeleteListener(itemID); - } - } - - // This method scans nearby objects and determines if they are listeners, - // and if so if this message fits the filter. If it does, then - // enqueue the message for delivery to the objects listen event handler. - // Objects that do an llSay have their messages delivered here, and for - // nearby avatars, the SimChat function is used. - public void DeliverMessage(string sourceItemID, ChatTypeEnum type, int channel, string name, string msg) - { - SceneObjectPart source = null; - ScenePresence avatar = null; - - source = m_scene.GetSceneObjectPart(new LLUUID(sourceItemID)); - if (source == null) - { - avatar = m_scene.GetScenePresence(new LLUUID(sourceItemID)); - } - if ((avatar != null) || (source != null)) - { - // Loop through the objects in the scene - // If they are in proximity, then if they are - // listeners, if so add them to the pending queue - - foreach (ListenerInfo li in m_listenerManager.GetListeners()) - { - EntityBase sPart; - - m_scene.Entities.TryGetValue(li.GetHostID(), out sPart); - - if (sPart != null) - { - double dis = 0; - - if (source != null) - dis = Util.GetDistanceTo(sPart.AbsolutePosition, source.AbsolutePosition); - else - dis = Util.GetDistanceTo(sPart.AbsolutePosition, avatar.AbsolutePosition); - - switch (type) - { - case ChatTypeEnum.Whisper: - - if ((dis < 10) && (dis > -10)) - { - if (li.GetChannel() == channel) - { - ListenerInfo isListener = m_listenerManager.IsListenerMatch( - sourceItemID, sPart.UUID, channel, name, msg - ); - if (isListener != null) - { - lock (m_pending.SyncRoot) - { - m_pending.Enqueue(isListener); - } - } - } - } - break; - - case ChatTypeEnum.Say: - - if ((dis < 30) && (dis > -30)) - { - if (li.GetChannel() == channel) - { - ListenerInfo isListener = m_listenerManager.IsListenerMatch( - sourceItemID, sPart.UUID, channel, name, msg - ); - if (isListener != null) - { - lock (m_pending.SyncRoot) - { - m_pending.Enqueue(isListener); - } - } - } - } - break; - - case ChatTypeEnum.Shout: - if ((dis < 100) && (dis > -100)) - { - if (li.GetChannel() == channel) - { - ListenerInfo isListener = m_listenerManager.IsListenerMatch( - sourceItemID, sPart.UUID, channel, name, msg - ); - if (isListener != null) - { - lock (m_pending.SyncRoot) - { - m_pending.Enqueue(isListener); - } - } - } - } - break; - - case ChatTypeEnum.Broadcast: - // Dont process if this message is from itself! - if (li.GetHostID().ToString().Equals(sourceItemID) || - sPart.UUID.ToString().Equals(sourceItemID)) - continue; - - if (li.GetChannel() == channel) - { - ListenerInfo isListener = m_listenerManager.IsListenerMatch( - sourceItemID, sPart.UUID, channel, name, msg - ); - if (isListener != null) - { - lock (m_pending.SyncRoot) - { - m_pending.Enqueue(isListener); - } - } - } - - break; - } - } - } - } - } - - public bool HasMessages() - { - if (m_pending != null) - return (m_pending.Count > 0); - else - return false; - } - - public ListenerInfo GetNextMessage() - { - ListenerInfo li = null; - - lock (m_pending.SyncRoot) - { - li = (ListenerInfo) m_pending.Dequeue(); - } - - return li; - } - - public uint PeekNextMessageLocalID() - { - return ((ListenerInfo) m_pending.Peek()).GetLocalID(); - } - - public LLUUID PeekNextMessageItemID() - { - return ((ListenerInfo) m_pending.Peek()).GetItemID(); - } - - #endregion - - public void NewClient(IClientAPI client) - { - client.OnChatFromViewer += DeliverClientMessage; - } - - /******************************************************************** - * - * Listener Stuff - * - * *****************************************************************/ - - private void DeliverClientMessage(Object sender, ChatFromViewerArgs e) - { - DeliverMessage(e.Sender.AgentId.ToString(), - e.Type, e.Channel, - e.Sender.FirstName + " " + e.Sender.LastName, - e.Message); - } - } - - public class ListenerManager - { - //private Dictionary m_listeners; - private object ListenersLock = new object(); - private Hashtable m_listeners = Hashtable.Synchronized(new Hashtable()); - private int m_MaxListeners = 100; - - public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg) - { - if (m_listeners.Count < m_MaxListeners) - { - ListenerInfo isListener = IsListenerMatch(LLUUID.Zero.ToString(), itemID, channel, name, msg); - - if (isListener == null) - { - int newHandle = GetNewHandle(); - - if (newHandle > -1) - { - ListenerInfo li = new ListenerInfo(localID, newHandle, itemID, hostID, channel, name, id, msg); - - lock (m_listeners.SyncRoot) - { - m_listeners.Add(newHandle, li); - } - - return newHandle; - } - } - } - - return -1; - } - - public void Remove(int handle) - { - lock (m_listeners.SyncRoot) - { - m_listeners.Remove(handle); - } - } - - public void DeleteListener(LLUUID itemID) - { - ArrayList removedListeners = new ArrayList(); - - lock (m_listeners.SyncRoot) - { - IDictionaryEnumerator en = m_listeners.GetEnumerator(); - while (en.MoveNext()) - { - ListenerInfo li = (ListenerInfo) en.Value; - if (li.GetItemID().Equals(itemID)) - { - removedListeners.Add(li.GetHandle()); - } - } - foreach (int handle in removedListeners) - { - m_listeners.Remove(handle); - } - } - } - - private int GetNewHandle() - { - for (int i = 0; i < int.MaxValue - 1; i++) - { - if (!m_listeners.ContainsKey(i)) - return i; - } - - return -1; - } - - public bool IsListener(LLUUID hostID) - { - foreach (ListenerInfo li in m_listeners.Values) - { - if (li.GetHostID().Equals(hostID)) - return true; - } - - return false; - } - - public void Activate(int handle) - { - if (m_listeners.ContainsKey(handle)) - { - lock (m_listeners.SyncRoot) - { - ListenerInfo li = (ListenerInfo) m_listeners[handle]; - li.Activate(); - } - } - } - - public void Dectivate(int handle) - { - if (m_listeners.ContainsKey(handle)) - { - ListenerInfo li = (ListenerInfo) m_listeners[handle]; - li.Deactivate(); - } - } - - // Theres probably a more clever and efficient way to - // do this, maybe with regex. - public ListenerInfo IsListenerMatch(string sourceItemID, LLUUID listenerKey, int channel, string name, - string msg) - { - bool isMatch = true; - lock (m_listeners.SyncRoot) - { - IDictionaryEnumerator en = m_listeners.GetEnumerator(); - while (en.MoveNext()) - { - ListenerInfo li = (ListenerInfo) en.Value; - - if (li.IsActive()) - { - if (li.GetHostID().Equals(listenerKey)) - { - if (channel == li.GetChannel()) - { - if ((li.GetID().ToString().Length > 0) && - (!li.GetID().Equals(LLUUID.Zero))) - { - if (!li.GetID().ToString().Equals(sourceItemID)) - { - isMatch = false; - } - } - if (isMatch && (li.GetName().Length > 0)) - { - if (li.GetName().Equals(name)) - { - isMatch = false; - } - } - if (isMatch) - { - return new ListenerInfo( - li.GetLocalID(), li.GetHandle(), li.GetItemID(), li.GetHostID(), - li.GetChannel(), name, li.GetID(), msg, new LLUUID(sourceItemID) - ); - } - } - } - } - } - } - return null; - } - - public ICollection GetListeners() - { - return m_listeners.Values; - } - } - - public class ListenerInfo - { - private bool m_active; // Listener is active or not - private int m_channel; // Channel - private int m_handle; // Assigned handle of this listener - private LLUUID m_hostID; // ID of the host/scene part - private LLUUID m_id; // ID to filter messages from - private LLUUID m_itemID; // ID of the host script engine - private uint m_localID; // Local ID from script engine - private string m_message; // The message - private string m_name; // Object name to filter messages from - private LLUUID m_sourceItemID; // ID of the scenePart or avatar source of the message - - public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, string message) - { - Initialise(localID, handle, ItemID, hostID, channel, name, id, message); - } - - public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, - string message, LLUUID sourceItemID) - { - Initialise(localID, handle, ItemID, hostID, channel, name, id, message); - m_sourceItemID = sourceItemID; - } - - private void Initialise(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, - LLUUID id, string message) - { - m_handle = handle; - m_channel = channel; - m_itemID = ItemID; - m_hostID = hostID; - m_name = name; - m_id = id; - m_message = message; - m_active = true; - m_localID = localID; - } - - public LLUUID GetItemID() - { - return m_itemID; - } - - public LLUUID GetHostID() - { - return m_hostID; - } - - public LLUUID GetSourceItemID() - { - return m_sourceItemID; - } - - public int GetChannel() - { - return m_channel; - } - - public uint GetLocalID() - { - return m_localID; - } - - public int GetHandle() - { - return m_handle; - } - - public string GetMessage() - { - return m_message; - } - - public string GetName() - { - return m_name; - } - - public bool IsActive() - { - return m_active; - } - - public void Deactivate() - { - m_active = false; - } - - public void Activate() - { - m_active = true; - } - - public LLUUID GetID() - { - return m_id; - } - } +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +/***************************************************** + * + * WorldCommModule + * + * + * Holding place for world comms - basically llListen + * function implementation. + * + * lLListen(integer channel, string name, key id, string msg) + * The name, id, and msg arguments specify the filtering + * criteria. You can pass the empty string + * (or NULL_KEY for id) for these to set a completely + * open filter; this causes the listen() event handler to be + * invoked for all chat on the channel. To listen only + * for chat spoken by a specific object or avatar, + * specify the name and/or id arguments. To listen + * only for a specific command, specify the + * (case-sensitive) msg argument. If msg is not empty, + * listener will only hear strings which are exactly equal + * to msg. You can also use all the arguments to establish + * the most restrictive filtering criteria. + * + * It might be useful for each listener to maintain a message + * digest, with a list of recent messages by UUID. This can + * be used to prevent in-world repeater loops. However, the + * linden functions do not have this capability, so for now + * thats the way it works. + * + * **************************************************/ + +namespace OpenSim.Region.Environment.Modules.Scripting.WorldComm +{ + public class WorldCommModule : IRegionModule, IWorldComm + { + private object CommListLock = new object(); + private object ListLock = new object(); + private ListenerManager m_listenerManager; + private string m_name = "WorldCommModule"; + private Queue m_pending; + private Queue m_pendingQ; + private Scene m_scene; + + public WorldCommModule() + { + } + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + m_scene.RegisterModuleInterface(this); + m_listenerManager = new ListenerManager(); + m_scene.EventManager.OnNewClient += NewClient; + m_pendingQ = new Queue(); + m_pending = Queue.Synchronized(m_pendingQ); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return m_name; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + + #region IWorldComm Members + + public int Listen(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg) + { + return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg); + } + + public void ListenControl(int handle, int active) + { + if (m_listenerManager != null) + { + if (active == 1) + m_listenerManager.Activate(handle); + else if (active == 0) + m_listenerManager.Dectivate(handle); + } + } + + public void ListenRemove(int handle) + { + if (m_listenerManager != null) + { + m_listenerManager.Remove(handle); + } + } + + public void DeleteListener(LLUUID itemID) + { + if (m_listenerManager != null) + { + m_listenerManager.DeleteListener(itemID); + } + } + + // This method scans nearby objects and determines if they are listeners, + // and if so if this message fits the filter. If it does, then + // enqueue the message for delivery to the objects listen event handler. + // Objects that do an llSay have their messages delivered here, and for + // nearby avatars, the SimChat function is used. + public void DeliverMessage(string sourceItemID, ChatTypeEnum type, int channel, string name, string msg) + { + SceneObjectPart source = null; + ScenePresence avatar = null; + + source = m_scene.GetSceneObjectPart(new LLUUID(sourceItemID)); + if (source == null) + { + avatar = m_scene.GetScenePresence(new LLUUID(sourceItemID)); + } + if ((avatar != null) || (source != null)) + { + // Loop through the objects in the scene + // If they are in proximity, then if they are + // listeners, if so add them to the pending queue + + foreach (ListenerInfo li in m_listenerManager.GetListeners()) + { + EntityBase sPart; + + m_scene.Entities.TryGetValue(li.GetHostID(), out sPart); + + if (sPart != null) + { + double dis = 0; + + if (source != null) + dis = Util.GetDistanceTo(sPart.AbsolutePosition, source.AbsolutePosition); + else + dis = Util.GetDistanceTo(sPart.AbsolutePosition, avatar.AbsolutePosition); + + switch (type) + { + case ChatTypeEnum.Whisper: + + if ((dis < 10) && (dis > -10)) + { + if (li.GetChannel() == channel) + { + ListenerInfo isListener = m_listenerManager.IsListenerMatch( + sourceItemID, sPart.UUID, channel, name, msg + ); + if (isListener != null) + { + lock (m_pending.SyncRoot) + { + m_pending.Enqueue(isListener); + } + } + } + } + break; + + case ChatTypeEnum.Say: + + if ((dis < 30) && (dis > -30)) + { + if (li.GetChannel() == channel) + { + ListenerInfo isListener = m_listenerManager.IsListenerMatch( + sourceItemID, sPart.UUID, channel, name, msg + ); + if (isListener != null) + { + lock (m_pending.SyncRoot) + { + m_pending.Enqueue(isListener); + } + } + } + } + break; + + case ChatTypeEnum.Shout: + if ((dis < 100) && (dis > -100)) + { + if (li.GetChannel() == channel) + { + ListenerInfo isListener = m_listenerManager.IsListenerMatch( + sourceItemID, sPart.UUID, channel, name, msg + ); + if (isListener != null) + { + lock (m_pending.SyncRoot) + { + m_pending.Enqueue(isListener); + } + } + } + } + break; + + case ChatTypeEnum.Broadcast: + // Dont process if this message is from itself! + if (li.GetHostID().ToString().Equals(sourceItemID) || + sPart.UUID.ToString().Equals(sourceItemID)) + continue; + + if (li.GetChannel() == channel) + { + ListenerInfo isListener = m_listenerManager.IsListenerMatch( + sourceItemID, sPart.UUID, channel, name, msg + ); + if (isListener != null) + { + lock (m_pending.SyncRoot) + { + m_pending.Enqueue(isListener); + } + } + } + + break; + } + } + } + } + } + + public bool HasMessages() + { + if (m_pending != null) + return (m_pending.Count > 0); + else + return false; + } + + public ListenerInfo GetNextMessage() + { + ListenerInfo li = null; + + lock (m_pending.SyncRoot) + { + li = (ListenerInfo) m_pending.Dequeue(); + } + + return li; + } + + public uint PeekNextMessageLocalID() + { + return ((ListenerInfo) m_pending.Peek()).GetLocalID(); + } + + public LLUUID PeekNextMessageItemID() + { + return ((ListenerInfo) m_pending.Peek()).GetItemID(); + } + + #endregion + + public void NewClient(IClientAPI client) + { + client.OnChatFromViewer += DeliverClientMessage; + } + + /******************************************************************** + * + * Listener Stuff + * + * *****************************************************************/ + + private void DeliverClientMessage(Object sender, ChatFromViewerArgs e) + { + DeliverMessage(e.Sender.AgentId.ToString(), + e.Type, e.Channel, + e.Sender.FirstName + " " + e.Sender.LastName, + e.Message); + } + } + + public class ListenerManager + { + //private Dictionary m_listeners; + private object ListenersLock = new object(); + private Hashtable m_listeners = Hashtable.Synchronized(new Hashtable()); + private int m_MaxListeners = 100; + + public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg) + { + if (m_listeners.Count < m_MaxListeners) + { + ListenerInfo isListener = IsListenerMatch(LLUUID.Zero.ToString(), itemID, channel, name, msg); + + if (isListener == null) + { + int newHandle = GetNewHandle(); + + if (newHandle > -1) + { + ListenerInfo li = new ListenerInfo(localID, newHandle, itemID, hostID, channel, name, id, msg); + + lock (m_listeners.SyncRoot) + { + m_listeners.Add(newHandle, li); + } + + return newHandle; + } + } + } + + return -1; + } + + public void Remove(int handle) + { + lock (m_listeners.SyncRoot) + { + m_listeners.Remove(handle); + } + } + + public void DeleteListener(LLUUID itemID) + { + ArrayList removedListeners = new ArrayList(); + + lock (m_listeners.SyncRoot) + { + IDictionaryEnumerator en = m_listeners.GetEnumerator(); + while (en.MoveNext()) + { + ListenerInfo li = (ListenerInfo) en.Value; + if (li.GetItemID().Equals(itemID)) + { + removedListeners.Add(li.GetHandle()); + } + } + foreach (int handle in removedListeners) + { + m_listeners.Remove(handle); + } + } + } + + private int GetNewHandle() + { + for (int i = 0; i < int.MaxValue - 1; i++) + { + if (!m_listeners.ContainsKey(i)) + return i; + } + + return -1; + } + + public bool IsListener(LLUUID hostID) + { + foreach (ListenerInfo li in m_listeners.Values) + { + if (li.GetHostID().Equals(hostID)) + return true; + } + + return false; + } + + public void Activate(int handle) + { + if (m_listeners.ContainsKey(handle)) + { + lock (m_listeners.SyncRoot) + { + ListenerInfo li = (ListenerInfo) m_listeners[handle]; + li.Activate(); + } + } + } + + public void Dectivate(int handle) + { + if (m_listeners.ContainsKey(handle)) + { + ListenerInfo li = (ListenerInfo) m_listeners[handle]; + li.Deactivate(); + } + } + + // Theres probably a more clever and efficient way to + // do this, maybe with regex. + public ListenerInfo IsListenerMatch(string sourceItemID, LLUUID listenerKey, int channel, string name, + string msg) + { + bool isMatch = true; + lock (m_listeners.SyncRoot) + { + IDictionaryEnumerator en = m_listeners.GetEnumerator(); + while (en.MoveNext()) + { + ListenerInfo li = (ListenerInfo) en.Value; + + if (li.IsActive()) + { + if (li.GetHostID().Equals(listenerKey)) + { + if (channel == li.GetChannel()) + { + if ((li.GetID().ToString().Length > 0) && + (!li.GetID().Equals(LLUUID.Zero))) + { + if (!li.GetID().ToString().Equals(sourceItemID)) + { + isMatch = false; + } + } + if (isMatch && (li.GetName().Length > 0)) + { + if (li.GetName().Equals(name)) + { + isMatch = false; + } + } + if (isMatch) + { + return new ListenerInfo( + li.GetLocalID(), li.GetHandle(), li.GetItemID(), li.GetHostID(), + li.GetChannel(), name, li.GetID(), msg, new LLUUID(sourceItemID) + ); + } + } + } + } + } + } + return null; + } + + public ICollection GetListeners() + { + return m_listeners.Values; + } + } + + public class ListenerInfo + { + private bool m_active; // Listener is active or not + private int m_channel; // Channel + private int m_handle; // Assigned handle of this listener + private LLUUID m_hostID; // ID of the host/scene part + private LLUUID m_id; // ID to filter messages from + private LLUUID m_itemID; // ID of the host script engine + private uint m_localID; // Local ID from script engine + private string m_message; // The message + private string m_name; // Object name to filter messages from + private LLUUID m_sourceItemID; // ID of the scenePart or avatar source of the message + + public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, string message) + { + Initialise(localID, handle, ItemID, hostID, channel, name, id, message); + } + + public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, + string message, LLUUID sourceItemID) + { + Initialise(localID, handle, ItemID, hostID, channel, name, id, message); + m_sourceItemID = sourceItemID; + } + + private void Initialise(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, + LLUUID id, string message) + { + m_handle = handle; + m_channel = channel; + m_itemID = ItemID; + m_hostID = hostID; + m_name = name; + m_id = id; + m_message = message; + m_active = true; + m_localID = localID; + } + + public LLUUID GetItemID() + { + return m_itemID; + } + + public LLUUID GetHostID() + { + return m_hostID; + } + + public LLUUID GetSourceItemID() + { + return m_sourceItemID; + } + + public int GetChannel() + { + return m_channel; + } + + public uint GetLocalID() + { + return m_localID; + } + + public int GetHandle() + { + return m_handle; + } + + public string GetMessage() + { + return m_message; + } + + public string GetName() + { + return m_name; + } + + public bool IsActive() + { + return m_active; + } + + public void Deactivate() + { + m_active = false; + } + + public void Activate() + { + m_active = true; + } + + public LLUUID GetID() + { + return m_id; + } + } } \ 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 index 6ca8136..a039d42 100644 --- a/OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs +++ b/OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs @@ -1,672 +1,672 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Net; -using System.Reflection; -using System.Threading; -using libsecondlife; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -/***************************************************** - * - * XMLRPCModule - * - * Module for accepting incoming communications from - * external XMLRPC client and calling a remote data - * procedure for a registered data channel/prim. - * - * - * 1. On module load, open a listener port - * 2. Attach an XMLRPC handler - * 3. When a request is received: - * 3.1 Parse into components: channel key, int, string - * 3.2 Look up registered channel listeners - * 3.3 Call the channel (prim) remote data method - * 3.4 Capture the response (llRemoteDataReply) - * 3.5 Return response to client caller - * 3.6 If no response from llRemoteDataReply within - * RemoteReplyScriptTimeout, generate script timeout fault - * - * Prims in script must: - * 1. Open a remote data channel - * 1.1 Generate a channel ID - * 1.2 Register primid,channelid pair with module - * 2. Implement the remote data procedure handler - * - * llOpenRemoteDataChannel - * llRemoteDataReply - * remote_data(integer type, key channel, key messageid, string sender, integer ival, string sval) - * llCloseRemoteDataChannel - * - * **************************************************/ - -namespace OpenSim.Region.Environment.Modules.Scripting.XMLRPC -{ - public class XMLRPCModule : IRegionModule, IXMLRPC - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private string m_name = "XMLRPCModule"; - - // - private Dictionary m_openChannels; - private Dictionary m_pendingSRDResponses; - private int m_remoteDataPort = 0; - - private Dictionary m_rpcPending; - private Dictionary m_rpcPendingResponses; - private List m_scenes = new List(); - private int RemoteReplyScriptTimeout = 9000; - private int RemoteReplyScriptWait = 300; - private object XMLRPCListLock = new object(); - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - try - { - m_remoteDataPort = config.Configs["Network"].GetInt("remoteDataPort", m_remoteDataPort); - } - catch (Exception) - { - } - - if (!m_scenes.Contains(scene)) - { - m_scenes.Add(scene); - - scene.RegisterModuleInterface(this); - } - } - - public void PostInitialise() - { - if (IsEnabled()) - { - m_openChannels = new Dictionary(); - m_rpcPending = new Dictionary(); - m_rpcPendingResponses = new Dictionary(); - m_pendingSRDResponses = new Dictionary(); - - // Start http server - // Attach xmlrpc handlers - m_log.Info("[REMOTE_DATA]: " + - "Starting XMLRPC Server on port " + m_remoteDataPort + " for llRemoteData commands."); - BaseHttpServer httpServer = new BaseHttpServer((uint) m_remoteDataPort); - httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData); - httpServer.Start(); - } - } - - public void Close() - { - } - - public string Name - { - get { return m_name; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - #region IXMLRPC Members - - public bool IsEnabled() - { - return (m_remoteDataPort > 0); - } - - /********************************************** - * OpenXMLRPCChannel - * - * Generate a LLUUID channel key and add it and - * the prim id to dictionary - * - * First check if there is a channel assigned for - * this itemID. If there is, then someone called - * llOpenRemoteDataChannel twice. Just return the - * original channel. Other option is to delete the - * current channel and assign a new one. - * - * ********************************************/ - - public LLUUID OpenXMLRPCChannel(uint localID, LLUUID itemID) - { - LLUUID channel = new LLUUID(); - - //Is a dupe? - foreach (RPCChannelInfo ci in m_openChannels.Values) - { - if (ci.GetItemID().Equals(itemID)) - { - // return the original channel ID for this item - channel = ci.GetChannelID(); - break; - } - } - - if (channel == LLUUID.Zero) - { - channel = LLUUID.Random(); - RPCChannelInfo rpcChanInfo = new RPCChannelInfo(localID, itemID, channel); - lock (XMLRPCListLock) - { - m_openChannels.Add(channel, rpcChanInfo); - } - } - - return channel; - } - - // Delete channels based on itemID - // for when a script is deleted - public void DeleteChannels(LLUUID itemID) - { - if (m_openChannels != null) - { - ArrayList tmp = new ArrayList(); - - lock (XMLRPCListLock) - { - foreach (RPCChannelInfo li in m_openChannels.Values) - { - if (li.GetItemID().Equals(itemID)) - { - tmp.Add(itemID); - } - } - - IEnumerator tmpEnumerator = tmp.GetEnumerator(); - while (tmpEnumerator.MoveNext()) - m_openChannels.Remove((LLUUID) tmpEnumerator.Current); - } - } - } - - /********************************************** - * Remote Data Reply - * - * Response to RPC message - * - *********************************************/ - - public void RemoteDataReply(string channel, string message_id, string sdata, int idata) - { - RPCRequestInfo rpcInfo; - LLUUID message_key = new LLUUID(message_id); - - if (m_rpcPendingResponses.TryGetValue(message_key, out rpcInfo)) - { - rpcInfo.SetStrRetval(sdata); - rpcInfo.SetIntRetval(idata); - rpcInfo.SetProcessed(true); - m_rpcPendingResponses.Remove(message_key); - } - } - - /********************************************** - * CloseXMLRPCChannel - * - * Remove channel from dictionary - * - *********************************************/ - - public void CloseXMLRPCChannel(LLUUID channelKey) - { - if (m_openChannels.ContainsKey(channelKey)) - m_openChannels.Remove(channelKey); - } - - - public bool hasRequests() - { - lock (XMLRPCListLock) - { - if (m_rpcPending != null) - return (m_rpcPending.Count > 0); - else - return false; - } - } - - public RPCRequestInfo GetNextCompletedRequest() - { - if (m_rpcPending != null) - { - lock (XMLRPCListLock) - { - foreach (LLUUID luid in m_rpcPending.Keys) - { - RPCRequestInfo tmpReq; - - if (m_rpcPending.TryGetValue(luid, out tmpReq)) - { - if (!tmpReq.IsProcessed()) return tmpReq; - } - } - } - } - return null; - } - - public void RemoveCompletedRequest(LLUUID id) - { - lock (XMLRPCListLock) - { - RPCRequestInfo tmp; - if (m_rpcPending.TryGetValue(id, out tmp)) - { - m_rpcPending.Remove(id); - m_rpcPendingResponses.Add(id, tmp); - } - else - { - Console.WriteLine("UNABLE TO REMOVE COMPLETED REQUEST"); - } - } - } - - public LLUUID SendRemoteData(uint localID, LLUUID itemID, string channel, string dest, int idata, string sdata) - { - SendRemoteDataRequest req = new SendRemoteDataRequest( - localID, itemID, channel, dest, idata, sdata - ); - m_pendingSRDResponses.Add(req.GetReqID(), req); - return req.process(); - } - - public SendRemoteDataRequest GetNextCompletedSRDRequest() - { - if (m_pendingSRDResponses != null) - { - lock (XMLRPCListLock) - { - foreach (LLUUID luid in m_pendingSRDResponses.Keys) - { - SendRemoteDataRequest tmpReq; - - if (m_pendingSRDResponses.TryGetValue(luid, out tmpReq)) - { - if (tmpReq.finished) - return tmpReq; - } - } - } - } - return null; - } - - public void RemoveCompletedSRDRequest(LLUUID id) - { - lock (XMLRPCListLock) - { - SendRemoteDataRequest tmpReq; - if (m_pendingSRDResponses.TryGetValue(id, out tmpReq)) - { - m_pendingSRDResponses.Remove(id); - } - } - } - - public void CancelSRDRequests(LLUUID itemID) - { - if (m_pendingSRDResponses != null) - { - lock (XMLRPCListLock) - { - foreach (SendRemoteDataRequest li in m_pendingSRDResponses.Values) - { - if (li.m_itemID.Equals(itemID)) - m_pendingSRDResponses.Remove(li.GetReqID()); - } - } - } - } - - #endregion - - public XmlRpcResponse XmlRpcRemoteData(XmlRpcRequest request) - { - XmlRpcResponse response = new XmlRpcResponse(); - - Hashtable requestData = (Hashtable) request.Params[0]; - bool GoodXML = (requestData.Contains("Channel") && requestData.Contains("IntValue") && - requestData.Contains("StringValue")); - - if (GoodXML) - { - LLUUID channel = new LLUUID((string) requestData["Channel"]); - RPCChannelInfo rpcChanInfo; - if (m_openChannels.TryGetValue(channel, out rpcChanInfo)) - { - string intVal = (string) requestData["IntValue"]; - string strVal = (string) requestData["StringValue"]; - - RPCRequestInfo rpcInfo; - - lock (XMLRPCListLock) - { - rpcInfo = - new RPCRequestInfo(rpcChanInfo.GetLocalID(), rpcChanInfo.GetItemID(), channel, strVal, - intVal); - m_rpcPending.Add(rpcInfo.GetMessageID(), rpcInfo); - } - - int timeoutCtr = 0; - - while (!rpcInfo.IsProcessed() && (timeoutCtr < RemoteReplyScriptTimeout)) - { - Thread.Sleep(RemoteReplyScriptWait); - timeoutCtr += RemoteReplyScriptWait; - } - if (rpcInfo.IsProcessed()) - { - Hashtable param = new Hashtable(); - param["StringValue"] = rpcInfo.GetStrRetval(); - param["IntValue"] = Convert.ToString(rpcInfo.GetIntRetval()); - - ArrayList parameters = new ArrayList(); - parameters.Add(param); - - response.Value = parameters; - rpcInfo = null; - } - else - { - response.SetFault(-1, "Script timeout"); - rpcInfo = null; - } - } - else - { - response.SetFault(-1, "Invalid channel"); - } - } - - return response; - } - } - - public class RPCRequestInfo - { - private LLUUID m_ChannelKey; - private string m_IntVal; - private LLUUID m_ItemID; - private uint m_localID; - private LLUUID m_MessageID; - private bool m_processed; - private int m_respInt; - private string m_respStr; - private string m_StrVal; - - public RPCRequestInfo(uint localID, LLUUID itemID, LLUUID channelKey, string strVal, string intVal) - { - m_localID = localID; - m_StrVal = strVal; - m_IntVal = intVal; - m_ItemID = itemID; - m_ChannelKey = channelKey; - m_MessageID = LLUUID.Random(); - m_processed = false; - m_respStr = String.Empty; - m_respInt = 0; - } - - public bool IsProcessed() - { - return m_processed; - } - - public LLUUID GetChannelKey() - { - return m_ChannelKey; - } - - public void SetProcessed(bool processed) - { - m_processed = processed; - } - - public void SetStrRetval(string resp) - { - m_respStr = resp; - } - - public string GetStrRetval() - { - return m_respStr; - } - - public void SetIntRetval(int resp) - { - m_respInt = resp; - } - - public int GetIntRetval() - { - return m_respInt; - } - - public uint GetLocalID() - { - return m_localID; - } - - public LLUUID GetItemID() - { - return m_ItemID; - } - - public string GetStrVal() - { - return m_StrVal; - } - - public int GetIntValue() - { - return int.Parse(m_IntVal); - } - - public LLUUID GetMessageID() - { - return m_MessageID; - } - } - - public class RPCChannelInfo - { - private LLUUID m_ChannelKey; - private LLUUID m_itemID; - private uint m_localID; - - public RPCChannelInfo(uint localID, LLUUID itemID, LLUUID channelID) - { - m_ChannelKey = channelID; - m_localID = localID; - m_itemID = itemID; - } - - public LLUUID GetItemID() - { - return m_itemID; - } - - public LLUUID GetChannelID() - { - return m_ChannelKey; - } - - public uint GetLocalID() - { - return m_localID; - } - } - - public class SendRemoteDataRequest - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - public string channel; - public string destURL; - public bool finished; - private Thread httpThread; - public int idata; - public LLUUID m_itemID; - public uint m_localID; - public LLUUID reqID; - public XmlRpcRequest request; - public int response_idata; - public string response_sdata; - public string sdata; - - public SendRemoteDataRequest(uint localID, LLUUID itemID, string channel, string dest, int idata, string sdata) - { - this.channel = channel; - destURL = dest; - this.idata = idata; - this.sdata = sdata; - m_itemID = itemID; - m_localID = localID; - - reqID = LLUUID.Random(); - } - - public LLUUID process() - { - httpThread = new Thread(SendRequest); - httpThread.Name = "HttpRequestThread"; - httpThread.Priority = ThreadPriority.BelowNormal; - httpThread.IsBackground = true; - finished = false; - httpThread.Start(); - ThreadTracker.Add(httpThread); - - return reqID; - } - - /* - * TODO: More work on the response codes. Right now - * returning 200 for success or 499 for exception - */ - - public void SendRequest() - { - Hashtable param = new Hashtable(); - - // Check if channel is an LLUUID - // if not, use as method name - LLUUID parseUID; - string mName = "llRemoteData"; - if ((channel != null) && (channel != "")) - if (!LLUUID.TryParse(channel, out parseUID)) - mName = channel; - else - param["Channel"] = channel; - - param["StringValue"] = sdata; - param["IntValue"] = Convert.ToString(idata); - - ArrayList parameters = new ArrayList(); - parameters.Add(param); - XmlRpcRequest req = new XmlRpcRequest(mName, parameters); - try - { - XmlRpcResponse resp = req.Send(destURL, 30000); - if (resp != null) - { - Hashtable respParms; - if (resp.Value.GetType().Equals(Type.GetType("System.Collections.Hashtable"))) - { - respParms = (Hashtable) resp.Value; - } - else - { - ArrayList respData = (ArrayList) resp.Value; - respParms = (Hashtable) respData[0]; - } - if (respParms != null) - { - if (respParms.Contains("StringValue")) - { - sdata = (string) respParms["StringValue"]; - } - if (respParms.Contains("IntValue")) - { - idata = Convert.ToInt32((string) respParms["IntValue"]); - } - if (respParms.Contains("faultString")) - { - sdata = (string) respParms["faultString"]; - } - if (respParms.Contains("faultCode")) - { - idata = Convert.ToInt32(respParms["faultCode"]); - } - } - } - } - catch (WebException we) - { - sdata = we.Message; - m_log.Warn("[SendRemoteDataRequest]: Request failed"); - m_log.Warn(we.StackTrace); - } - - finished = true; - } - - public void Stop() - { - try - { - httpThread.Abort(); - } - catch (Exception) - { - } - } - - public LLUUID GetReqID() - { - return reqID; - } - } +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Net; +using System.Reflection; +using System.Threading; +using libsecondlife; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Servers; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +/***************************************************** + * + * XMLRPCModule + * + * Module for accepting incoming communications from + * external XMLRPC client and calling a remote data + * procedure for a registered data channel/prim. + * + * + * 1. On module load, open a listener port + * 2. Attach an XMLRPC handler + * 3. When a request is received: + * 3.1 Parse into components: channel key, int, string + * 3.2 Look up registered channel listeners + * 3.3 Call the channel (prim) remote data method + * 3.4 Capture the response (llRemoteDataReply) + * 3.5 Return response to client caller + * 3.6 If no response from llRemoteDataReply within + * RemoteReplyScriptTimeout, generate script timeout fault + * + * Prims in script must: + * 1. Open a remote data channel + * 1.1 Generate a channel ID + * 1.2 Register primid,channelid pair with module + * 2. Implement the remote data procedure handler + * + * llOpenRemoteDataChannel + * llRemoteDataReply + * remote_data(integer type, key channel, key messageid, string sender, integer ival, string sval) + * llCloseRemoteDataChannel + * + * **************************************************/ + +namespace OpenSim.Region.Environment.Modules.Scripting.XMLRPC +{ + public class XMLRPCModule : IRegionModule, IXMLRPC + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private string m_name = "XMLRPCModule"; + + // + private Dictionary m_openChannels; + private Dictionary m_pendingSRDResponses; + private int m_remoteDataPort = 0; + + private Dictionary m_rpcPending; + private Dictionary m_rpcPendingResponses; + private List m_scenes = new List(); + private int RemoteReplyScriptTimeout = 9000; + private int RemoteReplyScriptWait = 300; + private object XMLRPCListLock = new object(); + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + try + { + m_remoteDataPort = config.Configs["Network"].GetInt("remoteDataPort", m_remoteDataPort); + } + catch (Exception) + { + } + + if (!m_scenes.Contains(scene)) + { + m_scenes.Add(scene); + + scene.RegisterModuleInterface(this); + } + } + + public void PostInitialise() + { + if (IsEnabled()) + { + m_openChannels = new Dictionary(); + m_rpcPending = new Dictionary(); + m_rpcPendingResponses = new Dictionary(); + m_pendingSRDResponses = new Dictionary(); + + // Start http server + // Attach xmlrpc handlers + m_log.Info("[REMOTE_DATA]: " + + "Starting XMLRPC Server on port " + m_remoteDataPort + " for llRemoteData commands."); + BaseHttpServer httpServer = new BaseHttpServer((uint) m_remoteDataPort); + httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData); + httpServer.Start(); + } + } + + public void Close() + { + } + + public string Name + { + get { return m_name; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + #region IXMLRPC Members + + public bool IsEnabled() + { + return (m_remoteDataPort > 0); + } + + /********************************************** + * OpenXMLRPCChannel + * + * Generate a LLUUID channel key and add it and + * the prim id to dictionary + * + * First check if there is a channel assigned for + * this itemID. If there is, then someone called + * llOpenRemoteDataChannel twice. Just return the + * original channel. Other option is to delete the + * current channel and assign a new one. + * + * ********************************************/ + + public LLUUID OpenXMLRPCChannel(uint localID, LLUUID itemID) + { + LLUUID channel = new LLUUID(); + + //Is a dupe? + foreach (RPCChannelInfo ci in m_openChannels.Values) + { + if (ci.GetItemID().Equals(itemID)) + { + // return the original channel ID for this item + channel = ci.GetChannelID(); + break; + } + } + + if (channel == LLUUID.Zero) + { + channel = LLUUID.Random(); + RPCChannelInfo rpcChanInfo = new RPCChannelInfo(localID, itemID, channel); + lock (XMLRPCListLock) + { + m_openChannels.Add(channel, rpcChanInfo); + } + } + + return channel; + } + + // Delete channels based on itemID + // for when a script is deleted + public void DeleteChannels(LLUUID itemID) + { + if (m_openChannels != null) + { + ArrayList tmp = new ArrayList(); + + lock (XMLRPCListLock) + { + foreach (RPCChannelInfo li in m_openChannels.Values) + { + if (li.GetItemID().Equals(itemID)) + { + tmp.Add(itemID); + } + } + + IEnumerator tmpEnumerator = tmp.GetEnumerator(); + while (tmpEnumerator.MoveNext()) + m_openChannels.Remove((LLUUID) tmpEnumerator.Current); + } + } + } + + /********************************************** + * Remote Data Reply + * + * Response to RPC message + * + *********************************************/ + + public void RemoteDataReply(string channel, string message_id, string sdata, int idata) + { + RPCRequestInfo rpcInfo; + LLUUID message_key = new LLUUID(message_id); + + if (m_rpcPendingResponses.TryGetValue(message_key, out rpcInfo)) + { + rpcInfo.SetStrRetval(sdata); + rpcInfo.SetIntRetval(idata); + rpcInfo.SetProcessed(true); + m_rpcPendingResponses.Remove(message_key); + } + } + + /********************************************** + * CloseXMLRPCChannel + * + * Remove channel from dictionary + * + *********************************************/ + + public void CloseXMLRPCChannel(LLUUID channelKey) + { + if (m_openChannels.ContainsKey(channelKey)) + m_openChannels.Remove(channelKey); + } + + + public bool hasRequests() + { + lock (XMLRPCListLock) + { + if (m_rpcPending != null) + return (m_rpcPending.Count > 0); + else + return false; + } + } + + public RPCRequestInfo GetNextCompletedRequest() + { + if (m_rpcPending != null) + { + lock (XMLRPCListLock) + { + foreach (LLUUID luid in m_rpcPending.Keys) + { + RPCRequestInfo tmpReq; + + if (m_rpcPending.TryGetValue(luid, out tmpReq)) + { + if (!tmpReq.IsProcessed()) return tmpReq; + } + } + } + } + return null; + } + + public void RemoveCompletedRequest(LLUUID id) + { + lock (XMLRPCListLock) + { + RPCRequestInfo tmp; + if (m_rpcPending.TryGetValue(id, out tmp)) + { + m_rpcPending.Remove(id); + m_rpcPendingResponses.Add(id, tmp); + } + else + { + Console.WriteLine("UNABLE TO REMOVE COMPLETED REQUEST"); + } + } + } + + public LLUUID SendRemoteData(uint localID, LLUUID itemID, string channel, string dest, int idata, string sdata) + { + SendRemoteDataRequest req = new SendRemoteDataRequest( + localID, itemID, channel, dest, idata, sdata + ); + m_pendingSRDResponses.Add(req.GetReqID(), req); + return req.process(); + } + + public SendRemoteDataRequest GetNextCompletedSRDRequest() + { + if (m_pendingSRDResponses != null) + { + lock (XMLRPCListLock) + { + foreach (LLUUID luid in m_pendingSRDResponses.Keys) + { + SendRemoteDataRequest tmpReq; + + if (m_pendingSRDResponses.TryGetValue(luid, out tmpReq)) + { + if (tmpReq.finished) + return tmpReq; + } + } + } + } + return null; + } + + public void RemoveCompletedSRDRequest(LLUUID id) + { + lock (XMLRPCListLock) + { + SendRemoteDataRequest tmpReq; + if (m_pendingSRDResponses.TryGetValue(id, out tmpReq)) + { + m_pendingSRDResponses.Remove(id); + } + } + } + + public void CancelSRDRequests(LLUUID itemID) + { + if (m_pendingSRDResponses != null) + { + lock (XMLRPCListLock) + { + foreach (SendRemoteDataRequest li in m_pendingSRDResponses.Values) + { + if (li.m_itemID.Equals(itemID)) + m_pendingSRDResponses.Remove(li.GetReqID()); + } + } + } + } + + #endregion + + public XmlRpcResponse XmlRpcRemoteData(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + + Hashtable requestData = (Hashtable) request.Params[0]; + bool GoodXML = (requestData.Contains("Channel") && requestData.Contains("IntValue") && + requestData.Contains("StringValue")); + + if (GoodXML) + { + LLUUID channel = new LLUUID((string) requestData["Channel"]); + RPCChannelInfo rpcChanInfo; + if (m_openChannels.TryGetValue(channel, out rpcChanInfo)) + { + string intVal = (string) requestData["IntValue"]; + string strVal = (string) requestData["StringValue"]; + + RPCRequestInfo rpcInfo; + + lock (XMLRPCListLock) + { + rpcInfo = + new RPCRequestInfo(rpcChanInfo.GetLocalID(), rpcChanInfo.GetItemID(), channel, strVal, + intVal); + m_rpcPending.Add(rpcInfo.GetMessageID(), rpcInfo); + } + + int timeoutCtr = 0; + + while (!rpcInfo.IsProcessed() && (timeoutCtr < RemoteReplyScriptTimeout)) + { + Thread.Sleep(RemoteReplyScriptWait); + timeoutCtr += RemoteReplyScriptWait; + } + if (rpcInfo.IsProcessed()) + { + Hashtable param = new Hashtable(); + param["StringValue"] = rpcInfo.GetStrRetval(); + param["IntValue"] = Convert.ToString(rpcInfo.GetIntRetval()); + + ArrayList parameters = new ArrayList(); + parameters.Add(param); + + response.Value = parameters; + rpcInfo = null; + } + else + { + response.SetFault(-1, "Script timeout"); + rpcInfo = null; + } + } + else + { + response.SetFault(-1, "Invalid channel"); + } + } + + return response; + } + } + + public class RPCRequestInfo + { + private LLUUID m_ChannelKey; + private string m_IntVal; + private LLUUID m_ItemID; + private uint m_localID; + private LLUUID m_MessageID; + private bool m_processed; + private int m_respInt; + private string m_respStr; + private string m_StrVal; + + public RPCRequestInfo(uint localID, LLUUID itemID, LLUUID channelKey, string strVal, string intVal) + { + m_localID = localID; + m_StrVal = strVal; + m_IntVal = intVal; + m_ItemID = itemID; + m_ChannelKey = channelKey; + m_MessageID = LLUUID.Random(); + m_processed = false; + m_respStr = String.Empty; + m_respInt = 0; + } + + public bool IsProcessed() + { + return m_processed; + } + + public LLUUID GetChannelKey() + { + return m_ChannelKey; + } + + public void SetProcessed(bool processed) + { + m_processed = processed; + } + + public void SetStrRetval(string resp) + { + m_respStr = resp; + } + + public string GetStrRetval() + { + return m_respStr; + } + + public void SetIntRetval(int resp) + { + m_respInt = resp; + } + + public int GetIntRetval() + { + return m_respInt; + } + + public uint GetLocalID() + { + return m_localID; + } + + public LLUUID GetItemID() + { + return m_ItemID; + } + + public string GetStrVal() + { + return m_StrVal; + } + + public int GetIntValue() + { + return int.Parse(m_IntVal); + } + + public LLUUID GetMessageID() + { + return m_MessageID; + } + } + + public class RPCChannelInfo + { + private LLUUID m_ChannelKey; + private LLUUID m_itemID; + private uint m_localID; + + public RPCChannelInfo(uint localID, LLUUID itemID, LLUUID channelID) + { + m_ChannelKey = channelID; + m_localID = localID; + m_itemID = itemID; + } + + public LLUUID GetItemID() + { + return m_itemID; + } + + public LLUUID GetChannelID() + { + return m_ChannelKey; + } + + public uint GetLocalID() + { + return m_localID; + } + } + + public class SendRemoteDataRequest + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + public string channel; + public string destURL; + public bool finished; + private Thread httpThread; + public int idata; + public LLUUID m_itemID; + public uint m_localID; + public LLUUID reqID; + public XmlRpcRequest request; + public int response_idata; + public string response_sdata; + public string sdata; + + public SendRemoteDataRequest(uint localID, LLUUID itemID, string channel, string dest, int idata, string sdata) + { + this.channel = channel; + destURL = dest; + this.idata = idata; + this.sdata = sdata; + m_itemID = itemID; + m_localID = localID; + + reqID = LLUUID.Random(); + } + + public LLUUID process() + { + httpThread = new Thread(SendRequest); + httpThread.Name = "HttpRequestThread"; + httpThread.Priority = ThreadPriority.BelowNormal; + httpThread.IsBackground = true; + finished = false; + httpThread.Start(); + ThreadTracker.Add(httpThread); + + return reqID; + } + + /* + * TODO: More work on the response codes. Right now + * returning 200 for success or 499 for exception + */ + + public void SendRequest() + { + Hashtable param = new Hashtable(); + + // Check if channel is an LLUUID + // if not, use as method name + LLUUID parseUID; + string mName = "llRemoteData"; + if ((channel != null) && (channel != "")) + if (!LLUUID.TryParse(channel, out parseUID)) + mName = channel; + else + param["Channel"] = channel; + + param["StringValue"] = sdata; + param["IntValue"] = Convert.ToString(idata); + + ArrayList parameters = new ArrayList(); + parameters.Add(param); + XmlRpcRequest req = new XmlRpcRequest(mName, parameters); + try + { + XmlRpcResponse resp = req.Send(destURL, 30000); + if (resp != null) + { + Hashtable respParms; + if (resp.Value.GetType().Equals(Type.GetType("System.Collections.Hashtable"))) + { + respParms = (Hashtable) resp.Value; + } + else + { + ArrayList respData = (ArrayList) resp.Value; + respParms = (Hashtable) respData[0]; + } + if (respParms != null) + { + if (respParms.Contains("StringValue")) + { + sdata = (string) respParms["StringValue"]; + } + if (respParms.Contains("IntValue")) + { + idata = Convert.ToInt32((string) respParms["IntValue"]); + } + if (respParms.Contains("faultString")) + { + sdata = (string) respParms["faultString"]; + } + if (respParms.Contains("faultCode")) + { + idata = Convert.ToInt32(respParms["faultCode"]); + } + } + } + } + catch (WebException we) + { + sdata = we.Message; + m_log.Warn("[SendRemoteDataRequest]: Request failed"); + m_log.Warn(we.StackTrace); + } + + finished = true; + } + + public void Stop() + { + try + { + httpThread.Abort(); + } + catch (Exception) + { + } + } + + public LLUUID GetReqID() + { + return reqID; + } + } } \ No newline at end of file -- cgit v1.1