From 5e4d6cab00cb29cd088ab7b62ab13aff103b64cb Mon Sep 17 00:00:00 2001 From: onefang Date: Sun, 19 May 2019 21:24:15 +1000 Subject: Dump OpenSim 0.9.0.1 into it's own branch. --- .../DynamicTexture/DynamicTextureModule.cs | 147 +++--- .../Scripting/EMailModules/EmailModule.cs | 31 +- .../Scripting/HttpRequest/ScriptsHttpRequests.cs | 259 ++++++---- .../HttpRequest/Tests/ScriptsHttpRequestsTests.cs | 22 +- .../CoreModules/Scripting/LSLHttp/UrlModule.cs | 542 +++++++++++++-------- .../Scripting/LoadImageURL/LoadImageURLModule.cs | 56 ++- .../ScriptModuleComms/ScriptModuleCommsModule.cs | 10 +- .../VectorRender/Tests/VectorRenderModuleTests.cs | 48 +- .../Scripting/VectorRender/VectorRenderModule.cs | 122 +++-- .../Scripting/WorldComm/WorldCommModule.cs | 124 ++--- .../CoreModules/Scripting/XMLRPC/XMLRPCModule.cs | 6 +- 11 files changed, 793 insertions(+), 574 deletions(-) (limited to 'OpenSim/Region/CoreModules/Scripting') diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs index a686a4d..090cb7d 100644 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs @@ -135,17 +135,13 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture m_reuseableDynamicTextures.Store( GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID); } + updater.newTextureID = newTextureID; } - } - if (updater.UpdateTimer == 0) - { lock (Updaters) { - if (!Updaters.ContainsKey(updater.UpdaterID)) - { + if (Updaters.ContainsKey(updater.UpdaterID)) Updaters.Remove(updater.UpdaterID); - } } } } @@ -172,21 +168,20 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture } public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, - string extraParams, int updateTimer) + string extraParams) { - return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, updateTimer, false, 255); + return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, false, 255); } public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, - string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) + string extraParams, bool SetBlending, byte AlphaValue) { - return AddDynamicTextureURL(simID, primID, contentType, url, - extraParams, updateTimer, SetBlending, - (int)(DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES); + return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, SetBlending, + (DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES); } public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, - string extraParams, int updateTimer, bool SetBlending, + string extraParams, bool SetBlending, int disp, byte AlphaValue, int face) { if (RenderPlugins.ContainsKey(contentType)) @@ -196,7 +191,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture updater.PrimID = primID; updater.ContentType = contentType; updater.Url = url; - updater.UpdateTimer = updateTimer; updater.UpdaterID = UUID.Random(); updater.Params = extraParams; updater.BlendWithOldTexture = SetBlending; @@ -213,26 +207,27 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture } RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams); - return updater.UpdaterID; + return updater.newTextureID; } return UUID.Zero; } public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, - string extraParams, int updateTimer) + string extraParams) { - return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, false, 255); + return AddDynamicTextureData(simID, primID, contentType, data, extraParams, false, + (DISP_TEMP|DISP_EXPIRE), 255, ALL_SIDES); } public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, - string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) + string extraParams, bool SetBlending, byte AlphaValue) { - return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, SetBlending, - (int) (DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES); + return AddDynamicTextureData(simID, primID, contentType, data, extraParams, SetBlending, + (DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES); } public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, - string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face) + string extraParams, bool SetBlending, int disp, byte AlphaValue, int face) { if (!RenderPlugins.ContainsKey(contentType)) return UUID.Zero; @@ -258,7 +253,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture updater.PrimID = primID; updater.ContentType = contentType; updater.BodyData = data; - updater.UpdateTimer = updateTimer; updater.UpdaterID = UUID.Random(); updater.Params = extraParams; updater.BlendWithOldTexture = SetBlending; @@ -314,7 +308,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture updater.UpdatePart(part, (UUID)objReusableTextureUUID); } - return updater.UpdaterID; + return updater.newTextureID; } private string GenerateReusableTextureKey(string data, string extraParams) @@ -404,17 +398,15 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture public byte FrontAlpha = 255; public string Params; public UUID PrimID; - public bool SetNewFrontAlpha = false; public UUID SimUUID; public UUID UpdaterID; - public int UpdateTimer; public int Face; public int Disp; public string Url; + public UUID newTextureID; public DynamicTextureUpdater() { - UpdateTimer = 0; BodyData = null; } @@ -436,16 +428,23 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture // FIXME: Need to return the appropriate ID if only a single face is replaced. oldID = tmptex.DefaultTexture.TextureID; + // not using parts number of faces because that fails on old meshs if (Face == ALL_SIDES) { oldID = tmptex.DefaultTexture.TextureID; tmptex.DefaultTexture.TextureID = textureID; + for(int i = 0; i < tmptex.FaceTextures.Length; i++) + { + if(tmptex.FaceTextures[i] != null) + tmptex.FaceTextures[i].TextureID = textureID; + } } else { try { Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); + oldID = texface.TextureID; texface.TextureID = textureID; tmptex.FaceTextures[Face] = texface; } @@ -455,10 +454,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture } } - // I'm pretty sure we always want to force this to true - // I'm pretty sure noone whats to set fullbright true if it wasn't true before. - // tmptex.DefaultTexture.Fullbright = true; - part.UpdateTextureEntry(tmptex.GetBytes()); } @@ -478,26 +473,39 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture if (part == null || data == null || data.Length <= 1) { - string msg = + string msg = String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); - + return UUID.Zero; } byte[] assetData = null; AssetBase oldAsset = null; - + if (BlendWithOldTexture) { - Primitive.TextureEntryFace defaultFace = part.Shape.Textures.DefaultTexture; - if (defaultFace != null) + Primitive.TextureEntryFace curFace; + if(Face == ALL_SIDES) + curFace = part.Shape.Textures.DefaultTexture; + else { - oldAsset = scene.AssetService.Get(defaultFace.TextureID.ToString()); + try + { + curFace = part.Shape.Textures.GetFace((uint)Face); + } + catch + { + curFace = null; + } + } + if (curFace != null) + { + oldAsset = scene.AssetService.Get(curFace.TextureID.ToString()); if (oldAsset != null) - assetData = BlendTextures(data, oldAsset.Data, SetNewFrontAlpha, FrontAlpha); + assetData = BlendTextures(data, oldAsset.Data, FrontAlpha); } } @@ -548,42 +556,49 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture return asset.FullID; } - private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) + private byte[] BlendTextures(byte[] frontImage, byte[] backImage, byte newAlpha) { ManagedImage managedImage; Image image; - if (OpenJPEG.DecodeToImage(frontImage, out managedImage, out image)) + if (!OpenJPEG.DecodeToImage(frontImage, out managedImage, out image) || image == null) + return null; + + Bitmap image1 = new Bitmap(image); + image.Dispose(); + + if (!OpenJPEG.DecodeToImage(backImage, out managedImage, out image) || image == null) { - Bitmap image1 = new Bitmap(image); + image1.Dispose(); + return null; + } - if (OpenJPEG.DecodeToImage(backImage, out managedImage, out image)) - { - Bitmap image2 = new Bitmap(image); + Bitmap image2 = new Bitmap(image); + image.Dispose(); - if (setNewAlpha) - SetAlpha(ref image1, newAlpha); + if (newAlpha < 255) + SetAlpha(ref image1, newAlpha); - Bitmap joint = MergeBitMaps(image1, image2); + using(Bitmap joint = MergeBitMaps(image1, image2)) + { + image1.Dispose(); + image2.Dispose(); - byte[] result = new byte[0]; + byte[] result = new byte[0]; - try - { - result = OpenJPEG.EncodeFromImage(joint, true); - } - catch (Exception e) - { - m_log.ErrorFormat( - "[DYNAMICTEXTUREMODULE]: OpenJpeg Encode Failed. Exception {0}{1}", + try + { + result = OpenJPEG.EncodeFromImage(joint, true); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[DYNAMICTEXTUREMODULE]: OpenJpeg Encode Failed. Exception {0}{1}", e.Message, e.StackTrace); - } - - return result; } - } - return null; + return result; + } } public Bitmap MergeBitMaps(Bitmap front, Bitmap back) @@ -592,12 +607,12 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture 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; + using(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) diff --git a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs index 4e7ad75..d59cfa9 100644 --- a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs @@ -113,7 +113,7 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules } catch (Exception e) { - m_log.Error("[EMAIL] DefaultEmailModule not configured: " + e.Message); + m_log.Error("[EMAIL]: DefaultEmailModule not configured: " + e.Message); m_Enabled = false; return; } @@ -142,7 +142,7 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules } } - m_log.Info("[EMAIL] Activated DefaultEmailModule"); + m_log.Info("[EMAIL]: Activated DefaultEmailModule"); } public void RemoveRegion(Scene scene) @@ -224,8 +224,9 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules return null; } - private void resolveNamePositionRegionName(UUID objectID, out string ObjectName, out string ObjectAbsolutePosition, out string ObjectRegionName) + private bool resolveNamePositionRegionName(UUID objectID, out string ObjectName, out string ObjectAbsolutePosition, out string ObjectRegionName) { + ObjectName = ObjectAbsolutePosition = ObjectRegionName = String.Empty; string m_ObjectRegionName; int objectLocX; int objectLocY; @@ -239,15 +240,9 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules ObjectAbsolutePosition = "(" + objectLocX + ", " + objectLocY + ", " + objectLocZ + ")"; ObjectName = part.Name; ObjectRegionName = m_ObjectRegionName; - return; + return true; } - objectLocX = (int)part.AbsolutePosition.X; - objectLocY = (int)part.AbsolutePosition.Y; - objectLocZ = (int)part.AbsolutePosition.Z; - ObjectAbsolutePosition = "(" + objectLocX + ", " + objectLocY + ", " + objectLocZ + ")"; - ObjectName = part.Name; - ObjectRegionName = m_ObjectRegionName; - return; + return false; } /// @@ -273,12 +268,12 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules bool isEMailStrictMatch = EMailreStrict.IsMatch(address); if (!isEMailStrictMatch) { - m_log.Error("[EMAIL] REGEX Problem in EMail Address: "+address); + m_log.Error("[EMAIL]: REGEX Problem in EMail Address: "+address); return; } if ((subject.Length + body.Length) > m_MaxEmailSize) { - m_log.Error("[EMAIL] subject + body larger than limit of " + m_MaxEmailSize + " bytes"); + m_log.Error("[EMAIL]: subject + body larger than limit of " + m_MaxEmailSize + " bytes"); return; } @@ -286,7 +281,8 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules string LastObjectPosition = string.Empty; string LastObjectRegionName = string.Empty; - resolveNamePositionRegionName(objectID, out LastObjectName, out LastObjectPosition, out LastObjectRegionName); + if (!resolveNamePositionRegionName(objectID, out LastObjectName, out LastObjectPosition, out LastObjectRegionName)) + return; if (!address.EndsWith(m_InterObjectHostname)) { @@ -302,7 +298,8 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules //Subject emailMessage.Subject = subject; //TEXT Body - resolveNamePositionRegionName(objectID, out LastObjectName, out LastObjectPosition, out LastObjectRegionName); + if (!resolveNamePositionRegionName(objectID, out LastObjectName, out LastObjectPosition, out LastObjectRegionName)) + return; emailMessage.BodyText = "Object-Name: " + LastObjectName + "\nRegion: " + LastObjectRegionName + "\nLocal-Position: " + LastObjectPosition + "\n\n" + body; @@ -321,11 +318,11 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules emailMessage.Send(smtpServer); //Log - m_log.Info("[EMAIL] EMail sent to: " + address + " from object: " + objectID.ToString() + "@" + m_HostName); + m_log.Info("[EMAIL]: EMail sent to: " + address + " from object: " + objectID.ToString() + "@" + m_HostName); } catch (Exception e) { - m_log.Error("[EMAIL] DefaultEmailModule Exception: " + e.Message); + m_log.Error("[EMAIL]: DefaultEmailModule Exception: " + e.Message); } } else diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs index 9dfeb96..f5b575b 100644 --- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs +++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs @@ -28,15 +28,12 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Net; using System.Net.Mail; using System.Net.Security; -using System.Reflection; using System.Text; using System.Threading; using System.Security.Cryptography.X509Certificates; -using log4net; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -45,6 +42,7 @@ using OpenSim.Framework.Servers.HttpServer; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using Mono.Addins; +using Amib.Threading; /***************************************************** * @@ -108,6 +106,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest private Dictionary m_pendingRequests; private Scene m_scene; // private Queue rpcQueue = new Queue(); + public static SmartThreadPool ThreadPool = null; public HttpRequestModule() { @@ -191,7 +190,15 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest case (int)HttpRequestConstants.HTTP_BODY_MAXLENGTH: - // TODO implement me + int len; + if(int.TryParse(parms[i + 1], out len)) + { + if(len > HttpRequestClass.HttpBodyMaxLenMAX) + len = HttpRequestClass.HttpBodyMaxLenMAX; + else if(len < 64) //??? + len = 64; + htc.HttpBodyMaxLen = len; + } break; case (int)HttpRequestConstants.HTTP_VERIFY_CERT: @@ -216,20 +223,16 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest if (parms.Length - i < 2) break; - //Have we reached the end of the list of headers? - //End is marked by a string with a single digit. - //We already know we have at least one parameter - //so it is safe to do this check at top of loop. - if (Char.IsDigit(parms[i][0])) - break; - if (htc.HttpCustomHeaders == null) htc.HttpCustomHeaders = new List(); htc.HttpCustomHeaders.Add(parms[i]); htc.HttpCustomHeaders.Add(parms[i+1]); + int nexti = i + 2; + if (nexti >= parms.Length || Char.IsDigit(parms[nexti][0])) + break; - i += 2; + i = nexti; } break; @@ -239,7 +242,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest } } } - + htc.RequestModule = this; htc.LocalID = localID; htc.ItemID = itemID; @@ -276,7 +279,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest } public bool StartHttpRequest(HttpRequestClass req) - { + { if (!CheckAllowed(new Uri(req.Url))) return false; @@ -290,29 +293,18 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest return true; } - public void StopHttpRequestsForScript(UUID id) + public void StopHttpRequest(uint m_localID, UUID m_itemID) { if (m_pendingRequests != null) { - List keysToRemove = null; - lock (HttpListLock) { - foreach (HttpRequestClass req in m_pendingRequests.Values) + HttpRequestClass tmpReq; + if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq)) { - if (req.ItemID == id) - { - req.Stop(); - - if (keysToRemove == null) - keysToRemove = new List(); - - keysToRemove.Add(req.ReqID); - } + tmpReq.Stop(); + m_pendingRequests.Remove(m_itemID); } - - if (keysToRemove != null) - keysToRemove.ForEach(keyToRemove => m_pendingRequests.Remove(keyToRemove)); } } } @@ -330,13 +322,19 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest { lock (HttpListLock) { - foreach (HttpRequestClass req in m_pendingRequests.Values) + foreach (UUID luid in m_pendingRequests.Keys) { - if (req.Finished) - return req; + HttpRequestClass tmpReq; + + if (m_pendingRequests.TryGetValue(luid, out tmpReq)) + { + if (tmpReq.Finished) + { + return tmpReq; + } + } } } - return null; } @@ -363,9 +361,34 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); + HttpRequestClass.HttpBodyMaxLenMAX = config.Configs["Network"].GetInt("HttpBodyMaxLenMAX", 16384); + + m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config); + int maxThreads = 15; + + IConfig httpConfig = config.Configs["HttpRequestModule"]; + if (httpConfig != null) + { + maxThreads = httpConfig.GetInt("MaxPoolThreads", maxThreads); + } m_pendingRequests = new Dictionary(); + + // First instance sets this up for all sims + if (ThreadPool == null) + { + STPStartInfo startInfo = new STPStartInfo(); + startInfo.IdleTimeout = 2000; + startInfo.MaxWorkerThreads = maxThreads; + startInfo.MinWorkerThreads = 0; + startInfo.ThreadPriority = ThreadPriority.BelowNormal; + startInfo.StartSuspended = true; + startInfo.ThreadPoolName = "ScriptsHttpReq"; + + ThreadPool = new SmartThreadPool(startInfo); + ThreadPool.Start(); + } } public void AddRegion(Scene scene) @@ -392,6 +415,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest public void Close() { + ThreadPool.Shutdown(); } public string Name @@ -409,8 +433,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest public class HttpRequestClass : IServiceRequest { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - // Constants for parameters // public const int HTTP_BODY_MAXLENGTH = 2; // public const int HTTP_METHOD = 0; @@ -430,13 +452,17 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest { get { return _finished; } } - // public int HttpBodyMaxLen = 2048; // not implemented + + public static int HttpBodyMaxLenMAX = 16384; // Parameter members and default values + public int HttpBodyMaxLen = 2048; public string HttpMethod = "GET"; public string HttpMIMEType = "text/plain;charset=utf-8"; public int HttpTimeout; public bool HttpVerifyCert = true; + public IWorkItemResult WorkItem = null; + //public bool HttpVerboseThrottle = true; // not implemented public List HttpCustomHeaders = null; public bool HttpPragmaNoCache = true; @@ -484,15 +510,40 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest public void Process() { + _finished = false; + + lock (HttpRequestModule.ThreadPool) + WorkItem = HttpRequestModule.ThreadPool.QueueWorkItem(new WorkItemCallback(StpSendWrapper), null); + } + + private object StpSendWrapper(object o) + { SendRequest(); + return null; } + /* + * TODO: More work on the response codes. Right now + * returning 200 for success or 499 for exception + */ + public void SendRequest() { + HttpWebResponse response = null; + Stream resStream = null; + byte[] buf = new byte[HttpBodyMaxLenMAX + 16]; + string tempString = null; + int count = 0; + try { Request = (HttpWebRequest)WebRequest.Create(Url); - Request.AllowAutoRedirect = false; + Request.AllowAutoRedirect = false; + Request.KeepAlive = false; + + //This works around some buggy HTTP Servers like Lighttpd + Request.ServicePoint.Expect100Continue = false; + Request.Method = HttpMethod; Request.ContentType = HttpMIMEType; @@ -500,7 +551,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest { // We could hijack Connection Group Name to identify // a desired security exception. But at the moment we'll use a dummy header instead. -// Request.ConnectionGroupName = "NoVerify"; Request.Headers.Add("NoVerifyCert", "true"); } // else @@ -533,14 +583,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest } } - if (ResponseHeaders != null) - { - foreach (KeyValuePair entry in ResponseHeaders) - if (entry.Key.ToLower().Equals("user-agent") && Request is HttpWebRequest) - ((HttpWebRequest)Request).UserAgent = entry.Value; - else - Request.Headers[entry.Key] = entry.Value; - } + foreach (KeyValuePair entry in ResponseHeaders) + if (entry.Key.ToLower().Equals("user-agent")) + Request.UserAgent = entry.Value; + else + Request.Headers[entry.Key] = entry.Value; // Encode outbound data if (!string.IsNullOrEmpty(OutboundBody)) @@ -552,12 +599,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest bstream.Write(data, 0, data.Length); } + Request.Timeout = HttpTimeout; try { - IAsyncResult result = (IAsyncResult)Request.BeginGetResponse(ResponseCallback, null); - - ThreadPool.RegisterWaitForSingleObject( - result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), null, HttpTimeout, true); + // execute the request + response = (HttpWebResponse) Request.GetResponse(); } catch (WebException e) { @@ -565,67 +611,74 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest { throw; } + response = (HttpWebResponse)e.Response; + } - HttpWebResponse response = (HttpWebResponse)e.Response; + Status = (int)response.StatusCode; - Status = (int)response.StatusCode; - ResponseBody = response.StatusDescription; - _finished = true; - } - } - catch (Exception e) - { -// m_log.Debug( -// string.Format("[SCRIPTS HTTP REQUESTS]: Exception on request to {0} for {1} ", Url, ItemID), e); + resStream = response.GetResponseStream(); + int totalBodyBytes = 0; + int maxBytes = HttpBodyMaxLen; + if(maxBytes > buf.Length) + maxBytes = buf.Length; - Status = (int)OSHttpStatusCode.ClientErrorJoker; - ResponseBody = e.Message; - _finished = true; - } - } + // we need to read all allowed or UFT8 conversion may fail + do + { + // fill the buffer with data + count = resStream.Read(buf, totalBodyBytes, maxBytes - totalBodyBytes); + totalBodyBytes += count; + if (totalBodyBytes >= maxBytes) + break; - private void ResponseCallback(IAsyncResult ar) - { - HttpWebResponse response = null; + } while (count > 0); // any more data to read? - try - { - try + if(totalBodyBytes > 0) { - response = (HttpWebResponse)Request.EndGetResponse(ar); + tempString = Util.UTF8.GetString(buf, 0, totalBodyBytes); + ResponseBody = tempString.Replace("\r", ""); } - catch (WebException e) + else + ResponseBody = ""; + } + catch (WebException e) + { + if (e.Status == WebExceptionStatus.ProtocolError) { - if (e.Status != WebExceptionStatus.ProtocolError) + HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response; + Status = (int)webRsp.StatusCode; + try { - throw; + using (Stream responseStream = webRsp.GetResponseStream()) + { + using (StreamReader reader = new StreamReader(responseStream)) + ResponseBody = reader.ReadToEnd(); + } + } + catch + { + ResponseBody = webRsp.StatusDescription; } - - response = (HttpWebResponse)e.Response; } - - Status = (int)response.StatusCode; - - using (Stream stream = response.GetResponseStream()) + else { - StreamReader reader = new StreamReader(stream, Encoding.UTF8); - ResponseBody = reader.ReadToEnd(); - } + Status = (int)OSHttpStatusCode.ClientErrorJoker; + ResponseBody = e.Message; + } } catch (Exception e) { - Status = (int)OSHttpStatusCode.ClientErrorJoker; - ResponseBody = e.Message; - -// m_log.Debug( -// string.Format("[SCRIPTS HTTP REQUESTS]: Exception on response to {0} for {1} ", Url, ItemID), e); + // Don't crash on anything else } finally { + if (resStream != null) + resStream.Close(); if (response != null) response.Close(); - // We need to resubmit + + // We need to resubmit if ( (Status == (int)HttpStatusCode.MovedPermanently || Status == (int)HttpStatusCode.Found @@ -670,22 +723,24 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest else { _finished = true; + if (ResponseBody == null) + ResponseBody = String.Empty; } } } - private void TimeoutCallback(object state, bool timedOut) - { - if (timedOut) - Request.Abort(); - } - public void Stop() { -// m_log.DebugFormat("[SCRIPTS HTTP REQUESTS]: Stopping request to {0} for {1} ", Url, ItemID); - - if (Request != null) - Request.Abort(); + try + { + if (!WorkItem.Cancel()) + { + WorkItem.Cancel(true); + } + } + catch (Exception) + { + } } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs index d22487e..7e223d7 100644 --- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs +++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs @@ -45,7 +45,7 @@ using OpenSim.Tests.Common; namespace OpenSim.Region.CoreModules.Scripting.HttpRequest.Tests { class TestWebRequestCreate : IWebRequestCreate - { + { public TestWebRequest NextRequest { get; set; } public WebRequest Create(Uri uri) @@ -65,13 +65,13 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest.Tests public Func OnEndGetResponse { get; set; } - public TestWebRequest() : base() + public TestWebRequest() : base() { // Console.WriteLine("created"); } -// public TestWebRequest(SerializationInfo serializationInfo, StreamingContext streamingContext) -// : base(serializationInfo, streamingContext) +// public TestWebRequest(SerializationInfo serializationInfo, StreamingContext streamingContext) +// : base(serializationInfo, streamingContext) // { // Console.WriteLine("created"); // } @@ -97,7 +97,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest.Tests public string Response { get; set; } #pragma warning disable 0618 - public TestHttpWebResponse(SerializationInfo serializationInfo, StreamingContext streamingContext) + public TestHttpWebResponse(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext) {} #pragma warning restore 0618 @@ -111,24 +111,24 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest.Tests { WaitHandle m_wh = new ManualResetEvent(true); - object IAsyncResult.AsyncState + object IAsyncResult.AsyncState { get { throw new System.NotImplementedException (); } } - WaitHandle IAsyncResult.AsyncWaitHandle + WaitHandle IAsyncResult.AsyncWaitHandle { get { return m_wh; } } - bool IAsyncResult.CompletedSynchronously + bool IAsyncResult.CompletedSynchronously { get { return false; } } - bool IAsyncResult.IsCompleted + bool IAsyncResult.IsCompleted { get { return true; } } @@ -155,7 +155,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest.Tests TestHelpers.EnableLogging(); if (!Util.IsPlatformMono) - Assert.Ignore("Ignoring test since can only currently run on Mono"); + Assert.Ignore("Ignoring test since can only currently run on Mono"); string rawResponse = "boom"; @@ -163,7 +163,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest.Tests TestWebRequest twr = new TestWebRequest(); //twr.OnEndGetResponse += ar => new TestHttpWebResponse(null, new StreamingContext()); - twr.OnEndGetResponse += ar => + twr.OnEndGetResponse += ar => { SerializationInfo si = new SerializationInfo(typeof(HttpWebResponse), new FormatterConverter()); StreamingContext sc = new StreamingContext(); diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index 99a3122..11fc513 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs @@ -26,10 +26,11 @@ */ using System; -using System.Threading; using System.Collections.Generic; using System.Collections; using System.Reflection; +using System.Net; +using System.Net.Sockets; using log4net; using Mono.Addins; using Nini.Config; @@ -42,40 +43,17 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Scripting.LSLHttp { - /// - /// Data describing an external URL set up by a script. - /// public class UrlData { - /// - /// Scene object part hosting the script - /// public UUID hostID; - - /// - /// The item ID of the script that requested the URL. - /// public UUID itemID; - - /// - /// The script engine that runs the script. - /// public IScriptModule engine; - - /// - /// The generated URL. - /// public string url; - - /// - /// The random UUID component of the generated URL. - /// public UUID urlcode; - - /// - /// The external requests currently being processed or awaiting retrieval for this URL. - /// public Dictionary requests; + public bool isSsl; + public Scene scene; + public bool allowXss; } public class RequestData @@ -89,7 +67,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp //public ManualResetEvent ev; public bool requestDone; public int startTime; + public bool responseSent; public string uri; + public bool allowResponseType = false; + public UUID hostID; + public Scene scene; } /// @@ -102,40 +84,33 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); - /// - /// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the request ID - /// randomly generated when a request is received for this URL. - /// - /// - /// Manipulation or retrieval from this dictionary must be locked on m_UrlMap to preserve consistency with - /// m_UrlMap - /// - private Dictionary m_RequestMap = new Dictionary(); + protected Dictionary m_RequestMap = + new Dictionary(); - /// - /// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the full URL - /// - private Dictionary m_UrlMap = new Dictionary(); + protected Dictionary m_UrlMap = + new Dictionary(); - private uint m_HttpsPort = 0; - private IHttpServer m_HttpServer = null; - private IHttpServer m_HttpsServer = null; + protected bool m_enabled = false; + protected string m_ErrorStr; + protected uint m_HttpsPort = 0; + protected IHttpServer m_HttpServer = null; + protected IHttpServer m_HttpsServer = null; - public string ExternalHostNameForLSL { get; private set; } + public string ExternalHostNameForLSL { get; protected set; } /// /// The default maximum number of urls /// - public const int DefaultTotalUrls = 100; + public const int DefaultTotalUrls = 15000; /// /// Maximum number of external urls that can be set up by this module. /// public int TotalUrls { get; set; } - public Type ReplaceableInterface + public Type ReplaceableInterface { - get { return null; } + get { return typeof(IUrlModule); } } public string Name @@ -146,6 +121,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp public void Initialise(IConfigSource config) { IConfig networkConfig = config.Configs["Network"]; + m_enabled = false; if (networkConfig != null) { @@ -156,9 +132,31 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp if (ssl_enabled) m_HttpsPort = (uint)config.Configs["Network"].GetInt("https_port", (int)m_HttpsPort); } + else + { + m_ErrorStr = "[Network] configuration missing, HTTP listener for LSL disabled"; + m_log.Warn("[URL MODULE]: " + m_ErrorStr); + return; + } - if (ExternalHostNameForLSL == null) - ExternalHostNameForLSL = System.Environment.MachineName; + if (String.IsNullOrWhiteSpace(ExternalHostNameForLSL)) + { + m_ErrorStr = "ExternalHostNameForLSL not defined in configuration, HTTP listener for LSL disabled"; + m_log.Warn("[URL MODULE]: " + m_ErrorStr); + return; + } + + IPAddress ia = null; + ia = Util.GetHostFromDNS(ExternalHostNameForLSL); + if (ia == null) + { + m_ErrorStr = "Could not resolve ExternalHostNameForLSL, HTTP listener for LSL disabled"; + m_log.Warn("[URL MODULE]: " + m_ErrorStr); + return; + } + + m_enabled = true; + m_ErrorStr = String.Empty; IConfig llFunctionsConfig = config.Configs["LL-Functions"]; @@ -174,7 +172,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp public void AddRegion(Scene scene) { - if (m_HttpServer == null) + if (m_enabled && m_HttpServer == null) { // There can only be one // @@ -204,21 +202,39 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp public void RemoveRegion(Scene scene) { + // Drop references to that scene + foreach (KeyValuePair kvp in m_UrlMap) + { + if (kvp.Value.scene == scene) + kvp.Value.scene = null; + } + foreach (KeyValuePair kvp in m_RequestMap) + { + if (kvp.Value.scene == scene) + kvp.Value.scene = null; + } } public void Close() { } - public UUID RequestURL(IScriptModule engine, SceneObjectPart host, UUID itemID) + public UUID RequestURL(IScriptModule engine, SceneObjectPart host, UUID itemID, Hashtable options) { UUID urlcode = UUID.Random(); + if(!m_enabled) + { + engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", m_ErrorStr }); + return urlcode; + } + lock (m_UrlMap) { if (m_UrlMap.Count >= TotalUrls) { - engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); + engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", + "Too many URLs already open" }); return urlcode; } string url = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString() + "/"; @@ -229,20 +245,26 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp urlData.engine = engine; urlData.url = url; urlData.urlcode = urlcode; + urlData.isSsl = false; urlData.requests = new Dictionary(); - + urlData.scene = host.ParentGroup.Scene; + urlData.allowXss = false; + + if (options != null && options["allowXss"] != null) + urlData.allowXss = true; + m_UrlMap[url] = urlData; - + string uri = "/lslhttp/" + urlcode.ToString() + "/"; - - PollServiceEventArgs args + + PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000); args.Type = PollServiceEventArgs.EventType.LslHttp; m_HttpServer.AddPollServiceHTTPHandler(uri, args); - m_log.DebugFormat( - "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}", - uri, itemID, host.Name, host.LocalId); +// m_log.DebugFormat( +// "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}", +// uri, itemID, host.Name, host.LocalId); engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); } @@ -250,10 +272,16 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp return urlcode; } - public UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID) + public UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID, Hashtable options) { UUID urlcode = UUID.Random(); + if(!m_enabled) + { + engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", m_ErrorStr }); + return urlcode; + } + if (m_HttpsServer == null) { engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); @@ -264,7 +292,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp { if (m_UrlMap.Count >= TotalUrls) { - engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); + engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", + "Too many URLs already open" }); return urlcode; } string url = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + "/lslhttps/" + urlcode.ToString() + "/"; @@ -275,20 +304,25 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp urlData.engine = engine; urlData.url = url; urlData.urlcode = urlcode; + urlData.isSsl = true; urlData.requests = new Dictionary(); + urlData.allowXss = false; + + if (options != null && options["allowXss"] != null) + urlData.allowXss = true; m_UrlMap[url] = urlData; - + string uri = "/lslhttps/" + urlcode.ToString() + "/"; - - PollServiceEventArgs args + + PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000); args.Type = PollServiceEventArgs.EventType.LslHttp; m_HttpsServer.AddPollServiceHTTPHandler(uri, args); - m_log.DebugFormat( - "[URL MODULE]: Set up incoming secure request url {0} for {1} in {2} {3}", - uri, itemID, host.Name, host.LocalId); +// m_log.DebugFormat( +// "[URL MODULE]: Set up incoming secure request url {0} for {1} in {2} {3}", +// uri, itemID, host.Name, host.LocalId); engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); } @@ -307,18 +341,21 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp return; } - foreach (UUID req in data.requests.Keys) - m_RequestMap.Remove(req); + lock (m_RequestMap) + { + foreach (UUID req in data.requests.Keys) + m_RequestMap.Remove(req); + } - m_log.DebugFormat( - "[URL MODULE]: Releasing url {0} for {1} in {2}", - url, data.itemID, data.hostID); +// m_log.DebugFormat( +// "[URL MODULE]: Releasing url {0} for {1} in {2}", +// url, data.itemID, data.hostID); RemoveUrl(data); m_UrlMap.Remove(url); } } - + public void HttpContentType(UUID request, string type) { lock (m_UrlMap) @@ -334,32 +371,42 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp } } } - + public void HttpResponse(UUID request, int status, string body) { - lock (m_UrlMap) + lock (m_RequestMap) { if (m_RequestMap.ContainsKey(request)) { UrlData urlData = m_RequestMap[request]; - string responseBody = body; - if (urlData.requests[request].responseType.Equals("text/plain")) + if (!urlData.requests[request].responseSent) { - string value; - if (urlData.requests[request].headers.TryGetValue("user-agent", out value)) + string responseBody = body; + + // If we have no OpenID from built-in browser, disable this + if (!urlData.requests[request].allowResponseType) + urlData.requests[request].responseType = "text/plain"; + + if (urlData.requests[request].responseType.Equals("text/plain")) { - if (value != null && value.IndexOf("MSIE") >= 0) + string value; + if (urlData.requests[request].headers.TryGetValue("user-agent", out value)) { - // wrap the html escaped response if the target client is IE - // It ignores "text/plain" if the body is html - responseBody = "" + System.Web.HttpUtility.HtmlEncode(body) + ""; + if (value != null && value.IndexOf("MSIE") >= 0) + { + // wrap the html escaped response if the target client is IE + // It ignores "text/plain" if the body is html + responseBody = "" + System.Web.HttpUtility.HtmlEncode(body) + ""; + } } } + + urlData.requests[request].responseCode = status; + urlData.requests[request].responseBody = responseBody; + //urlData.requests[request].ev.Set(); + urlData.requests[request].requestDone = true; + urlData.requests[request].responseSent = true; } - urlData.requests[request].responseCode = status; - urlData.requests[request].responseBody = responseBody; - //urlData.requests[request].ev.Set(); - urlData.requests[request].requestDone =true; } else { @@ -370,7 +417,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp public string GetHttpHeader(UUID requestId, string header) { - lock (m_UrlMap) + lock (m_RequestMap) { if (m_RequestMap.ContainsKey(requestId)) { @@ -384,7 +431,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId); } } - return String.Empty; } @@ -397,7 +443,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp public void ScriptRemoved(UUID itemID) { // m_log.DebugFormat("[URL MODULE]: Removing script {0}", itemID); - + lock (m_UrlMap) { List removeURLs = new List(); @@ -408,8 +454,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp { RemoveUrl(url.Value); removeURLs.Add(url.Key); - foreach (UUID req in url.Value.requests.Keys) - m_RequestMap.Remove(req); + lock (m_RequestMap) + { + foreach (UUID req in url.Value.requests.Keys) + m_RequestMap.Remove(req); + } } } @@ -430,9 +479,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp { RemoveUrl(url.Value); removeURLs.Add(url.Key); - - foreach (UUID req in url.Value.requests.Keys) - m_RequestMap.Remove(req); + lock (m_RequestMap) + { + foreach (UUID req in url.Value.requests.Keys) + m_RequestMap.Remove(req); + } } } @@ -441,123 +492,131 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp } } - private void RemoveUrl(UrlData data) + + protected void RemoveUrl(UrlData data) { - m_HttpServer.RemoveHTTPHandler("", "/lslhttp/" + data.urlcode.ToString() + "/"); + if (data.isSsl) + m_HttpsServer.RemoveHTTPHandler("", "/lslhttps/"+data.urlcode.ToString()+"/"); + else + m_HttpServer.RemoveHTTPHandler("", "/lslhttp/"+data.urlcode.ToString()+"/"); } - private Hashtable NoEvents(UUID requestID, UUID sessionID) + protected Hashtable NoEvents(UUID requestID, UUID sessionID) { Hashtable response = new Hashtable(); - UrlData urlData; - - lock (m_UrlMap) + UrlData url; + int startTime = 0; + lock (m_RequestMap) { - // We need to return a 404 here in case the request URL was removed at exactly the same time that a - // request was made. In this case, the request thread can outrace llRemoveURL() and still be polling - // for the request ID. if (!m_RequestMap.ContainsKey(requestID)) - { - response["int_response_code"] = 404; - response["str_response_string"] = ""; - response["keepalive"] = false; - response["reusecontext"] = false; - return response; - } + url = m_RequestMap[requestID]; + startTime = url.requests[requestID].startTime; + } - urlData = m_RequestMap[requestID]; + if (System.Environment.TickCount - startTime > 25000) + { + response["int_response_code"] = 500; + response["str_response_string"] = "Script timeout"; + response["content_type"] = "text/plain"; + response["keepalive"] = false; + response["reusecontext"] = false; - if (System.Environment.TickCount - urlData.requests[requestID].startTime > 25000) + //remove from map + lock (url.requests) + { + url.requests.Remove(requestID); + } + lock (m_RequestMap) { - response["int_response_code"] = 500; - response["str_response_string"] = "Script timeout"; - response["content_type"] = "text/plain"; - response["keepalive"] = false; - response["reusecontext"] = false; - - //remove from map - urlData.requests.Remove(requestID); m_RequestMap.Remove(requestID); - - return response; } + + return response; } + return response; } - private bool HasEvents(UUID requestID, UUID sessionID) + protected bool HasEvents(UUID requestID, UUID sessionID) { - lock (m_UrlMap) + UrlData url=null; + + lock (m_RequestMap) { - // We return true here because an external URL request that happened at the same time as an llRemoveURL() - // can still make it through to HttpRequestHandler(). That will return without setting up a request - // when it detects that the URL has been removed. The poller, however, will continue to ask for - // events for that request, so here we will signal that there are events and in GetEvents we will - // return a 404. if (!m_RequestMap.ContainsKey(requestID)) { - return true; + return false; } - - UrlData urlData = m_RequestMap[requestID]; - - if (!urlData.requests.ContainsKey(requestID)) + url = m_RequestMap[requestID]; + } + lock (url.requests) + { + if (!url.requests.ContainsKey(requestID)) { - return true; + return false; } - - // Trigger return of timeout response. - if (System.Environment.TickCount - urlData.requests[requestID].startTime > 25000) + else { - return true; + if (System.Environment.TickCount - url.requests[requestID].startTime > 25000) + { + return true; + } + if (url.requests[requestID].requestDone) + return true; + else + return false; } - - return urlData.requests[requestID].requestDone; } } - - private Hashtable GetEvents(UUID requestID, UUID sessionID) + protected Hashtable GetEvents(UUID requestID, UUID sessionID) { - Hashtable response; + UrlData url = null; + RequestData requestData = null; - lock (m_UrlMap) + lock (m_RequestMap) { - UrlData url = null; - RequestData requestData = null; - if (!m_RequestMap.ContainsKey(requestID)) - return NoEvents(requestID, sessionID); - + return NoEvents(requestID,sessionID); url = m_RequestMap[requestID]; + } + lock (url.requests) + { requestData = url.requests[requestID]; + } - if (!requestData.requestDone) - return NoEvents(requestID, sessionID); - - response = new Hashtable(); + if (!requestData.requestDone) + return NoEvents(requestID,sessionID); - if (System.Environment.TickCount - requestData.startTime > 25000) - { - response["int_response_code"] = 500; - response["str_response_string"] = "Script timeout"; - response["content_type"] = "text/plain"; - response["keepalive"] = false; - response["reusecontext"] = false; - return response; - } + Hashtable response = new Hashtable(); - //put response - response["int_response_code"] = requestData.responseCode; - response["str_response_string"] = requestData.responseBody; - response["content_type"] = requestData.responseType; - // response["content_type"] = "text/plain"; + if (System.Environment.TickCount - requestData.startTime > 25000) + { + response["int_response_code"] = 500; + response["str_response_string"] = "Script timeout"; + response["content_type"] = "text/plain"; response["keepalive"] = false; response["reusecontext"] = false; - - //remove from map + return response; + } + //put response + response["int_response_code"] = requestData.responseCode; + response["str_response_string"] = requestData.responseBody; + response["content_type"] = requestData.responseType; + response["keepalive"] = false; + response["reusecontext"] = false; + + if (url.allowXss) + response["access_control_allow_origin"] = "*"; + + //remove from map + lock (url.requests) + { url.requests.Remove(requestID); + } + lock (m_RequestMap) + { m_RequestMap.Remove(requestID); } @@ -566,44 +625,49 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp public void HttpRequestHandler(UUID requestID, Hashtable request) { - string uri = request["uri"].ToString(); - bool is_ssl = uri.Contains("lslhttps"); - - try + lock (request) { - Hashtable headers = (Hashtable)request["headers"]; + string uri = request["uri"].ToString(); + bool is_ssl = uri.Contains("lslhttps"); -// string uri_full = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/"; + try + { + Hashtable headers = (Hashtable)request["headers"]; - int pos1 = uri.IndexOf("/");// /lslhttp - int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/ - int pos3 = uri.IndexOf("/", pos2 + 1);// /lslhttp// - string uri_tmp = uri.Substring(0, pos3 + 1); - //HTTP server code doesn't provide us with QueryStrings - string pathInfo; - string queryString; - queryString = ""; +// string uri_full = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/"; - pathInfo = uri.Substring(pos3); + int pos1 = uri.IndexOf("/");// /lslhttp + int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/ + int pos3 = uri.IndexOf("/", pos2 + 1); // /lslhttp/urlcode - UrlData urlData = null; + string uri_tmp = uri.Substring(0, pos3 + 1); + //HTTP server code doesn't provide us with QueryStrings + string pathInfo; + string queryString; + queryString = ""; - lock (m_UrlMap) - { - string url; + pathInfo = uri.Substring(pos3); - if (is_ssl) - url = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp; + UrlData url = null; + string urlkey; + if (!is_ssl) + urlkey = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp; + //m_UrlMap[]; else - url = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp; + urlkey = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp; - // Avoid a race - the request URL may have been released via llRequestUrl() whilst this - // request was being processed. - if (!m_UrlMap.TryGetValue(url, out urlData)) + if (m_UrlMap.ContainsKey(urlkey)) + { + url = m_UrlMap[urlkey]; + } + else + { + //m_log.Warn("[HttpRequestHandler]: http-in request failed; no such url: "+urlkey.ToString()); return; + } //for llGetHttpHeader support we need to store original URI here - //to make x-path-info / x-query-string / x-script-url / x-remote-ip headers + //to make x-path-info / x-query-string / x-script-url / x-remote-ip headers //as per http://wiki.secondlife.com/wiki/LlGetHTTPHeader RequestData requestData = new RequestData(); @@ -611,6 +675,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp requestData.requestDone = false; requestData.startTime = System.Environment.TickCount; requestData.uri = uri; + requestData.hostID = url.hostID; + requestData.scene = url.scene; if (requestData.headers == null) requestData.headers = new Dictionary(); @@ -619,8 +685,33 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp string key = (string)header.Key; string value = (string)header.Value; requestData.headers.Add(key, value); + if (key == "cookie") + { + string[] parts = value.Split(new char[] {'='}); + if (parts[0] == "agni_sl_session_id" && parts.Length > 1) + { + string cookie = Uri.UnescapeDataString(parts[1]); + string[] crumbs = cookie.Split(new char[] {':'}); + UUID owner; + if (crumbs.Length == 2 && UUID.TryParse(crumbs[0], out owner)) + { + if (crumbs[1].Length == 32) + { + Scene scene = requestData.scene; + if (scene != null) + { + SceneObjectPart host = scene.GetSceneObjectPart(requestData.hostID); + if (host != null) + { + if (host.OwnerID == owner) + requestData.allowResponseType = true; + } + } + } + } + } + } } - foreach (DictionaryEntry de in request) { if (de.Key.ToString() == "querystringkeys") @@ -631,13 +722,21 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp if (request.ContainsKey(key)) { string val = (String)request[key]; - queryString = queryString + key + "=" + val + "&"; + if (key != "") + { + queryString = queryString + key + "=" + val + "&"; + } + else + { + queryString = queryString + val + "&"; + } } } - if (queryString.Length > 1) queryString = queryString.Substring(0, queryString.Length - 1); + } + } //if this machine is behind DNAT/port forwarding, currently this is being @@ -645,27 +744,38 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp requestData.headers["x-remote-ip"] = requestData.headers["remote_addr"]; requestData.headers["x-path-info"] = pathInfo; requestData.headers["x-query-string"] = queryString; - requestData.headers["x-script-url"] = urlData.url; + requestData.headers["x-script-url"] = url.url; - urlData.requests.Add(requestID, requestData); - m_RequestMap.Add(requestID, urlData); - } + //requestData.ev = new ManualResetEvent(false); + lock (url.requests) + { + url.requests.Add(requestID, requestData); + } + lock (m_RequestMap) + { + //add to request map + m_RequestMap.Add(requestID, url); + } - urlData.engine.PostScriptEvent( - urlData.itemID, - "http_request", - new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() }); - } - catch (Exception we) - { - //Hashtable response = new Hashtable(); - m_log.Warn("[HttpRequestHandler]: http-in request failed"); - m_log.Warn(we.Message); - m_log.Warn(we.StackTrace); + url.engine.PostScriptEvent(url.itemID, "http_request", new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() }); + + //send initial response? +// Hashtable response = new Hashtable(); + + return; + + } + catch (Exception we) + { + //Hashtable response = new Hashtable(); + m_log.Warn("[HttpRequestHandler]: http-in request failed"); + m_log.Warn(we.Message); + m_log.Warn(we.StackTrace); + } } } - private void OnScriptReset(uint localID, UUID itemID) + protected void OnScriptReset(uint localID, UUID itemID) { ScriptRemoved(itemID); } diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs index d45962f..673a453 100644 --- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs @@ -98,7 +98,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL return false; } - public void GetDrawStringSize(string text, string fontName, int fontSize, + public void GetDrawStringSize(string text, string fontName, int fontSize, out double xSize, out double ySize) { xSize = 0; @@ -124,7 +124,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL { if (m_scene == null) m_scene = scene; - + } public void RemoveRegion(Scene scene) @@ -166,15 +166,15 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.AllowAutoRedirect = false; - - if (!string.IsNullOrEmpty(m_proxyurl)) + + if (!string.IsNullOrEmpty(m_proxyurl)) { - if (!string.IsNullOrEmpty(m_proxyexcepts)) + if (!string.IsNullOrEmpty(m_proxyexcepts)) { string[] elist = m_proxyexcepts.Split(';'); request.Proxy = new WebProxy(m_proxyurl, true, elist); - } - else + } + else { request.Proxy = new WebProxy(m_proxyurl, true); } @@ -253,7 +253,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL { imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); } - } + } catch (Exception) { m_log.Error("[LOADIMAGEURLMODULE]: OpenJpeg Conversion Failed. Empty byte data returned!"); @@ -268,33 +268,37 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL catch (WebException) { } + catch (Exception e) + { + m_log.ErrorFormat("[LOADIMAGEURLMODULE]: unexpected exception {0}", e.Message); + } finally { if (stream != null) stream.Close(); if (response != null) - response.Close(); - - if ( - response.StatusCode == HttpStatusCode.MovedPermanently - || response.StatusCode == HttpStatusCode.Found - || response.StatusCode == HttpStatusCode.SeeOther - || response.StatusCode == HttpStatusCode.TemporaryRedirect) { - string redirectedUrl = response.Headers["Location"]; + if (response.StatusCode == HttpStatusCode.MovedPermanently + || response.StatusCode == HttpStatusCode.Found + || response.StatusCode == HttpStatusCode.SeeOther + || response.StatusCode == HttpStatusCode.TemporaryRedirect) + { + string redirectedUrl = response.Headers["Location"]; - MakeHttpRequest(redirectedUrl, state.RequestID); - } - else - { - m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}", - imageJ2000.Length, state.RequestID); + MakeHttpRequest(redirectedUrl, state.RequestID); + } + else + { + m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}", + imageJ2000.Length, state.RequestID); - m_textureManager.ReturnData( - state.RequestID, - new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture( - request.RequestUri, null, imageJ2000, newSize, false)); + m_textureManager.ReturnData( + state.RequestID, + new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture( + request.RequestUri, null, imageJ2000, newSize, false)); + } + response.Close(); } } } diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index 6da2222..9c3f08e 100644 --- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -89,7 +89,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms public void RegionLoaded(Scene scene) { m_scriptModule = scene.RequestModuleInterface(); - + if (m_scriptModule != null) m_log.Info("[MODULE COMMANDS]: Script engine found, module active"); } @@ -237,7 +237,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms } } } - + public Delegate[] GetScriptInvocationList() { List ret = new List(); @@ -271,6 +271,8 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms return "modInvokeR"; else if (sid.ReturnType == typeof(object[])) return "modInvokeL"; + else if (sid.ReturnType == typeof(void)) + return "modInvokeN"; m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name); } @@ -359,14 +361,14 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms public object LookupModConstant(string cname) { // m_log.DebugFormat("[MODULE COMMANDS] lookup constant <{0}>",cname); - + lock (m_constants) { object value = null; if (m_constants.TryGetValue(cname,out value)) return value; } - + return null; } diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs index ed255bf..325f7f9 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs @@ -77,8 +77,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", - "", - 0); + ""); Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } @@ -98,8 +97,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; @@ -108,8 +106,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } @@ -129,8 +126,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; @@ -139,8 +135,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "alpha:250", - 0); + "alpha:250"); Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } @@ -161,8 +156,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; @@ -171,8 +165,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } @@ -191,8 +184,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", - "", - 0); + ""); Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } @@ -213,8 +205,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; @@ -223,8 +214,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } @@ -253,8 +243,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "1024", - 0); + "1024"); UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; @@ -263,8 +252,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "1024", - 0); + "1024"); Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } @@ -284,8 +272,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; @@ -294,8 +281,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "alpha:250", - 0); + "alpha:250"); Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } @@ -316,8 +302,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; @@ -326,8 +311,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index 4cecd85..8a26ab7 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs @@ -117,7 +117,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender return true; } - public void GetDrawStringSize(string text, string fontName, int fontSize, + public void GetDrawStringSize(string text, string fontName, int fontSize, out double xSize, out double ySize) { lock (this) @@ -209,32 +209,32 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender int alpha = 255; // 0 is transparent Color bgColor = Color.White; // Default background color char altDataDelim = ';'; - + char[] paramDelimiter = { ',' }; char[] nvpDelimiter = { ':' }; - + extraParams = extraParams.Trim(); extraParams = extraParams.ToLower(); - + string[] nvps = extraParams.Split(paramDelimiter); - + int temp = -1; foreach (string pair in nvps) { string[] nvp = pair.Split(nvpDelimiter); string name = ""; string value = ""; - + if (nvp[0] != null) { name = nvp[0].Trim(); } - + if (nvp.Length == 2) { value = nvp[1].Trim(); } - + switch (name) { case "width": @@ -301,7 +301,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender if (Int32.TryParse(value, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hex)) { bgColor = Color.FromArgb(hex); - } + } else { bgColor = Color.FromName(value); @@ -321,7 +321,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } else { - // this function used to accept an int on its own that represented both + // this function used to accept an int on its own that represented both // width and height, this is to maintain backwards compat, could be removed // but would break existing scripts temp = parseIntParam(name); @@ -329,10 +329,10 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender { if (temp > 1024) temp = 1024; - + if (temp < 128) temp = 128; - + width = temp; height = temp; } @@ -355,36 +355,28 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender lock (this) { if (alpha == 256) - bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); - else - bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); - - graph = Graphics.FromImage(bitmap); - - // this is really just to save people filling the - // background color in their scripts, only do when fully opaque - if (alpha >= 255) { + bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); + graph = Graphics.FromImage(bitmap); using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) { graph.FillRectangle(bgFillBrush, 0, 0, width, height); } - } - - for (int w = 0; w < bitmap.Width; w++) + } + else { - if (alpha <= 255) + bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); + graph = Graphics.FromImage(bitmap); + Color newbg = Color.FromArgb(alpha,bgColor); + using (SolidBrush bgFillBrush = new SolidBrush(newbg)) { - for (int h = 0; h < bitmap.Height; h++) - { - bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); - } + graph.FillRectangle(bgFillBrush, 0, 0, width, height); } } - + GDIDraw(data, graph, altDataDelim, out reuseable); } - + byte[] imageJ2000 = new byte[0]; // This code exists for testing purposes, please do not remove. @@ -394,7 +386,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender // imageJ2000 = s_asset2Data; // // s_flipper = !s_flipper; - + try { imageJ2000 = OpenJPEG.EncodeFromImage(bitmap, true); @@ -420,13 +412,13 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender { if (graph != null) graph.Dispose(); - + if (bitmap != null) bitmap.Dispose(); } } } - + private int parseIntParam(string strInt) { int parsed; @@ -440,7 +432,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender // m_log.Debug("Problem with Draw. Please verify parameters." + e.ToString()); parsed = -1; } - + return parsed; } @@ -519,8 +511,32 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender // m_log.DebugFormat("[VECTOR RENDER MODULE]: Processing line '{0}'", nextLine); + if (nextLine.StartsWith("ResetTransf")) + { + graph.ResetTransform(); + } + else if (nextLine.StartsWith("TransTransf")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 11, ref x, ref y); + graph.TranslateTransform(x, y); + } + else if (nextLine.StartsWith("ScaleTransf")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 11, ref x, ref y); + graph.ScaleTransform(x, y); + } + else if (nextLine.StartsWith("RotTransf")) + { + float x = 0; + GetParams(partsDelimiter, ref nextLine, 9, ref x); + graph.RotateTransform(x); + } //replace with switch, or even better, do some proper parsing - if (nextLine.StartsWith("MoveTo")) + else if (nextLine.StartsWith("MoveTo")) { float x = 0; float y = 0; @@ -572,7 +588,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender graph.DrawString("not an image. Please check URL.", errorFont, myBrush, new Point(startPoint.X, 12 + startPoint.Y)); } - + graph.DrawRectangle(drawPen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); } } @@ -625,6 +641,17 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender startPoint.X += endPoint.X; startPoint.Y += endPoint.Y; } + else if (nextLine.StartsWith("FillEllipse")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 11, ref x, ref y); + endPoint.X = (int)x; + endPoint.Y = (int)y; + graph.FillEllipse(myBrush, 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); @@ -638,11 +665,11 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender { nextLine = nextLine.Remove(0, 8); nextLine = nextLine.Trim(); - + string[] fprops = nextLine.Split(partsDelimiter); foreach (string prop in fprops) { - + switch (prop) { case "B": @@ -717,7 +744,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender else if (cap[0].ToLower() != "both") return; string type = cap[1].ToLower(); - + if (end) { switch (type) @@ -760,7 +787,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender nextLine = nextLine.Remove(0, 9); nextLine = nextLine.Trim(); int hex = 0; - + Color newColor; if (Int32.TryParse(nextLine, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hex)) { @@ -790,6 +817,17 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } } + private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x) + { + line = line.Remove(0, startLength); + string[] parts = line.Split(partsDelimiter); + if (parts.Length > 0) + { + string xVal = parts[0].Trim(); + x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture); + } + } + private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x, ref float y) { line = line.Remove(0, startLength); @@ -861,4 +899,4 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender return null; } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs index 3484387..a5203ea 100644 --- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs @@ -96,6 +96,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm // private static readonly ILog m_log = // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private const int DEBUG_CHANNEL = 2147483647; + private ListenerManager m_listenerManager; private Queue m_pending; private Queue m_pendingQ; @@ -111,7 +113,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm // wrap this in a try block so that defaults will work if // the config file doesn't specify otherwise. int maxlisteners = 1000; - int maxhandles = 64; + int maxhandles = 65; try { m_whisperdistance = config.Configs["Chat"].GetInt( @@ -128,8 +130,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm catch (Exception) { } - if (maxlisteners < 1) maxlisteners = int.MaxValue; - if (maxhandles < 1) maxhandles = int.MaxValue; + + if (maxlisteners < 1) + maxlisteners = int.MaxValue; + if (maxhandles < 1) + maxhandles = int.MaxValue; + + if (maxlisteners < maxhandles) + maxlisteners = maxhandles; + m_listenerManager = new ListenerManager(maxlisteners, maxhandles); m_pendingQ = new Queue(); m_pending = Queue.Synchronized(m_pendingQ); @@ -309,6 +318,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm // Determine which listen event filters match the given set of arguments, this results // in a limited set of listeners, each belonging a host. If the host is in range, add them // to the pending queue. + foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg)) @@ -366,79 +376,82 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm /// /// Message. /// - public void DeliverMessageTo(UUID target, int channel, Vector3 pos, - string name, UUID id, string msg) + public void DeliverMessageTo(UUID target, int channel, Vector3 pos, string name, UUID id, string msg) { - // Is id an avatar? - ScenePresence sp = m_scene.GetScenePresence(target); + if (channel == DEBUG_CHANNEL) + return; + if(target == UUID.Zero) + return; + + // Is target an avatar? + ScenePresence sp = m_scene.GetScenePresence(target); if (sp != null) { - // ignore if a child agent this is restricted to inside one - // region - if (sp.IsChildAgent) + // Send message to avatar + if (channel == 0) + { + // Channel 0 goes to viewer ONLY + m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, target, false, false); return; + } - // Channel zero only goes to the avatar - // non zero channel messages only go to the attachments of the avatar. - if (channel != 0) - { - List attachments = sp.GetAttachments(); - if (attachments.Count == 0) - return; + // for now messages to prims don't cross regions + if(sp.IsChildAgent) + return; - // Get uuid of attachments - List targets = new List(); - foreach (SceneObjectGroup sog in attachments) - { - if (!sog.IsDeleted) - targets.Add(sog.UUID); - } + List attachments = sp.GetAttachments(); + + if (attachments.Count == 0) + return; - // Need to check each attachment - foreach (ListenerInfo li - in m_listenerManager.GetListeners(UUID.Zero, - channel, name, id, msg)) + // Get uuid of attachments + List targets = new List(); + foreach (SceneObjectGroup sog in attachments) + { + if (!sog.IsDeleted) { - if (li.GetHostID().Equals(id)) - continue; + SceneObjectPart[] parts = sog.Parts; + foreach(SceneObjectPart p in parts) + targets.Add(p.UUID); + } + } - if (m_scene.GetSceneObjectPart( - li.GetHostID()) == null) - { - continue; - } + foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg)) + { + UUID liHostID = li.GetHostID(); + if (liHostID.Equals(id)) + continue; + if (m_scene.GetSceneObjectPart(liHostID) == null) + continue; - if (targets.Contains(li.GetHostID())) - QueueMessage(new ListenerInfo(li, name, id, msg)); - } + if (targets.Contains(liHostID)) + QueueMessage(new ListenerInfo(li, name, id, msg)); } return; } - // No avatar found so look for an object - foreach (ListenerInfo li - in m_listenerManager.GetListeners(UUID.Zero, channel, - name, id, msg)) + SceneObjectPart part = m_scene.GetSceneObjectPart(target); + if (part == null) // Not even an object + return; // No error + + foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg)) { + UUID liHostID = li.GetHostID(); // Dont process if this message is from yourself! - if (li.GetHostID().Equals(id)) + if (liHostID.Equals(id)) continue; - SceneObjectPart sPart = m_scene.GetSceneObjectPart( - li.GetHostID()); - if (sPart == null) + if (m_scene.GetSceneObjectPart(liHostID) == null) continue; - if (li.GetHostID().Equals(target)) + if (liHostID.Equals(target)) { QueueMessage(new ListenerInfo(li, name, id, msg)); break; } } - - return; } protected void QueueMessage(ListenerInfo li) @@ -557,9 +570,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm return coll[0].GetHandle(); } - if (m_curlisteners < m_maxlisteners) + lock (m_listeners) { - lock (m_listeners) + if (m_curlisteners < m_maxlisteners) { int newHandle = GetNewHandle(itemID); @@ -599,11 +612,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm li.GetHandle().Equals(handle)) { lis.Value.Remove(li); + m_curlisteners--; if (lis.Value.Count == 0) - { - m_listeners.Remove(lis.Key); - m_curlisteners--; - } + m_listeners.Remove(lis.Key); // bailing of loop so this does not smoke // there should be only one, so we bail out early return; } @@ -712,6 +723,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm } } + if(handles.Count >= m_maxhandles) + return -1; + // Note: 0 is NOT a valid handle for llListen() to return for (int i = 1; i <= m_maxhandles; i++) { diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs index 87f4277..6028eef 100644 --- a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs @@ -621,7 +621,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC private Thread httpThread; public int Idata; private UUID _itemID; - public UUID ItemID + public UUID ItemID { get { return _itemID; } set { _itemID = value; } @@ -633,7 +633,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC set { _localID = value; } } private UUID _reqID; - public UUID ReqID + public UUID ReqID { get { return _reqID; } set { _reqID = value; } @@ -658,7 +658,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC public void Process() { _finished = false; - httpThread = WorkManager.StartThread(SendRequest, "HttpRequestThread", ThreadPriority.BelowNormal, true, false); + httpThread = WorkManager.StartThread(SendRequest, "XMLRPCreqThread", ThreadPriority.BelowNormal, true, false, null, int.MaxValue); } /* -- cgit v1.1