From 3bdd4db3fd7eddb9e4f017cc45aa3eb2b3921111 Mon Sep 17 00:00:00 2001
From: Dahlia Trimble
Date: Sat, 10 Jan 2009 01:46:47 +0000
Subject: Thanks jhurliman for a patch that implements progressive texture
 downloading - Mantis #2655

---
 .../Agent/TextureDownload/TextureDownloadModule.cs |  58 ++--
 .../Agent/TextureDownload/TextureNotFoundSender.cs |   1 -
 .../TextureDownload/UserTextureDownloadService.cs  |   9 +-
 .../TextureSender/Tests/TextureSenderTests.cs      |   2 +-
 .../Modules/Agent/TextureSender/TextureSender.cs   | 307 ++++++++++++++-------
 .../Modules/Avatar/Friends/FriendsModule.cs        |   1 -
 .../Region/Environment/Scenes/Scene.Inventory.cs   |   1 -
 OpenSim/Region/ScriptEngine/XEngine/XEngine.cs     |  12 +-
 8 files changed, 256 insertions(+), 135 deletions(-)

(limited to 'OpenSim')

diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs
index 35fa5ed..2f5ea23 100644
--- a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs
+++ b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs
@@ -241,44 +241,52 @@ namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload
         {
             ITextureSender sender = null;
 
-            try
-            {
+//            try
+//            {
                 while (true)
                 {
-                    sender = m_queueSenders.Dequeue();
-
-                    if (sender.Cancel)
+                    try
                     {
-                        TextureSent(sender);
+                        sender = m_queueSenders.Dequeue();
 
-                        sender.Cancel = false;
-                    }
-                    else
-                    {
-                        bool finished = sender.SendTexturePacket();
-                        if (finished)
+                        if (sender.Cancel)
                         {
                             TextureSent(sender);
+
+                            sender.Cancel = false;
                         }
                         else
                         {
-                            m_queueSenders.Enqueue(sender);
+                            bool finished = sender.SendTexturePacket();
+                            if (finished)
+                            {
+                                TextureSent(sender);
+                            }
+                            else
+                            {
+                                m_queueSenders.Enqueue(sender);
+                            }
                         }
-                    }
 
-                    // Make sure that any sender we currently have can get garbage collected
-                    sender = null;
+                        // Make sure that any sender we currently have can get garbage collected
+                        sender = null;
 
-                    //m_log.InfoFormat("[TEXTURE] Texture sender queue size: {0}", m_queueSenders.Count());
+                        //m_log.InfoFormat("[TEXTURE] Texture sender queue size: {0}", m_queueSenders.Count());
+                    }
+                    catch(Exception e)
+                    {
+                        m_log.ErrorFormat(
+                            "[TEXTURE]: Texture send thread caught exception. The texture send was aborted. Exception is {0}", e);
+                    }
                 }
-            }
-            catch (Exception e)
-            {
-                // TODO: Let users in the sim and those entering it and possibly an external watchdog know what has happened
-                m_log.ErrorFormat(
-                    "[TEXTURE]: Texture send thread terminating with exception.  PLEASE REBOOT YOUR SIM - TEXTURES WILL NOT BE AVAILABLE UNTIL YOU DO.  Exception is {0}", 
-                    e);                
-            }            
+//            }
+//            catch (Exception e)
+//            {
+//                // TODO: Let users in the sim and those entering it and possibly an external watchdog know what has happened
+//                m_log.ErrorFormat(
+//                    "[TEXTURE]: Texture send thread terminating with exception.  PLEASE REBOOT YOUR SIM - TEXTURES WILL NOT BE AVAILABLE UNTIL YOU DO.  Exception is {0}", 
+//                    e);                
+//            }            
         }
 
         /// <summary>
diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs
index c064064..044ee76 100644
--- a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs
+++ b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs
@@ -28,7 +28,6 @@
 using System.Reflection;
 using log4net;
 using OpenMetaverse;
-using OpenMetaverse.Packets;
 using OpenSim.Framework;
 using OpenSim.Region.Environment.Interfaces;
 
diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs
index d6c9877..aab4ad0 100644
--- a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs
+++ b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs
@@ -56,11 +56,10 @@ namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload
         /// <summary>
         /// We will allow the client to request the same texture n times before dropping further requests
         ///
-        /// This number includes repeated requests for the same texture at different resolutions (which we don't
-        /// currently handle properly as far as I know).  However, this situation should be handled in a more
-        /// sophisticated way.
+        /// This number contains repeated requests for the same texture at different resolutions (which
+        /// are handled since r7368).  However, this situation should be handled in a more sophisticated way.
         /// </summary>
-        private static readonly int MAX_ALLOWED_TEXTURE_REQUESTS = 5;
+        private static readonly int MAX_ALLOWED_TEXTURE_REQUESTS = 15;
 
         /// <summary>
         /// XXX Also going to limit requests for found textures.
@@ -149,7 +148,7 @@ namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload
 
                         m_scene.AddPendingDownloads(1);
 
-                        TextureSender.TextureSender requestHandler = new TextureSender.TextureSender(m_client, e.DiscardLevel, e.PacketNumber);
+                        TextureSender.TextureSender requestHandler = new TextureSender.TextureSender(m_client, e.DiscardLevel, e.PacketNumber, e.Priority);
                         m_textureSenders.Add(e.RequestedAssetID, requestHandler);
 
                         m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback, true);
diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureSender/Tests/TextureSenderTests.cs b/OpenSim/Region/Environment/Modules/Agent/TextureSender/Tests/TextureSenderTests.cs
index 4049dfc..cff215b 100644
--- a/OpenSim/Region/Environment/Modules/Agent/TextureSender/Tests/TextureSenderTests.cs
+++ b/OpenSim/Region/Environment/Modules/Agent/TextureSender/Tests/TextureSenderTests.cs
@@ -53,7 +53,7 @@ namespace OpenSim.Region.Environment.Modules.Agent.TextureSender
             agent.startpos = Vector3.Zero;
             agent.CapsPath = "http://wibble.com";
             
-            new TextureSender(new TestClient(agent), 0, 0);
+            new TextureSender(new TestClient(agent), 0, 0, 1.0f);
         }
     }
 }
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs b/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs
index 57129dd..0e34271 100644
--- a/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs
+++ b/OpenSim/Region/Environment/Modules/Agent/TextureSender/TextureSender.cs
@@ -27,106 +27,188 @@
 
 using System;
 using System.Reflection;
-using OpenMetaverse.Packets;
 using log4net;
 using OpenSim.Framework;
 using OpenSim.Region.Environment.Interfaces;
 
 namespace OpenSim.Region.Environment.Modules.Agent.TextureSender
 {
-    /// <summary>
-    /// A TextureSender handles the process of receiving a texture requested by the client from the
-    /// AssetCache, and then sending that texture back to the client.
-    /// </summary>
-    public class TextureSender : ITextureSender
+    public class ImageDownload
     {
-        private static readonly ILog m_log
-            = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+        public const int FIRST_IMAGE_PACKET_SIZE = 600;
+        public const int IMAGE_PACKET_SIZE = 1000;
 
-        /// <summary>
-        /// Records the number of times texture send has been called.
-        /// </summary>
-        public int counter = 0;
+        public OpenMetaverse.AssetTexture Texture;
+        public int DiscardLevel;
+        public float Priority;
+        public int CurrentPacket;
+        public int StopPacket;
 
-        public bool ImageLoaded = false;
+        public ImageDownload(OpenMetaverse.AssetTexture texture, int discardLevel, float priority, int packet)
+        {
+            Texture = texture;
+            Update(discardLevel, priority, packet);
+        }
 
         /// <summary>
-        /// Holds the texture asset to send.
+        /// Updates an image transfer with new information and recalculates
+        /// offsets
         /// </summary>
-        private AssetBase m_asset;
+        /// <param name="discardLevel">New requested discard level</param>
+        /// <param name="priority">New requested priority</param>
+        /// <param name="packet">New requested packet offset</param>
+        public void Update(int discardLevel, float priority, int packet)
+        {
+            Priority = priority;
+            DiscardLevel = Clamp(discardLevel, 0, Texture.LayerInfo.Length - 1);
+            StopPacket = GetPacketForBytePosition(Texture.LayerInfo[(Texture.LayerInfo.Length - 1) - DiscardLevel].End);
+            CurrentPacket = Clamp(packet, 1, TexturePacketCount());
+        }
 
-        //public UUID assetID { get { return m_asset.FullID; } }
+        /// <summary>
+        /// Returns the total number of packets needed to transfer this texture,
+        /// including the first packet of size FIRST_IMAGE_PACKET_SIZE
+        /// </summary>
+        /// <returns>Total number of packets needed to transfer this texture</returns>
+        public int TexturePacketCount()
+        {
+            return ((Texture.AssetData.Length - FIRST_IMAGE_PACKET_SIZE + IMAGE_PACKET_SIZE - 1) / IMAGE_PACKET_SIZE) + 1;
+        }
 
-        // private bool m_cancel = false;
+        /// <summary>
+        /// Returns the current byte offset for this transfer, calculated from
+        /// the CurrentPacket
+        /// </summary>
+        /// <returns>Current byte offset for this transfer</returns>
+        public int CurrentBytePosition()
+        {
+            return FIRST_IMAGE_PACKET_SIZE + (CurrentPacket - 1) * IMAGE_PACKET_SIZE;
+        }
 
-        // See ITextureSender
+        /// <summary>
+        /// Returns the size, in bytes, of the last packet. This will be somewhere
+        /// between 1 and IMAGE_PACKET_SIZE bytes
+        /// </summary>
+        /// <returns>Size of the last packet in the transfer</returns>
+        public int LastPacketSize()
+        {
+            return Texture.AssetData.Length - (FIRST_IMAGE_PACKET_SIZE + ((TexturePacketCount() - 2) * IMAGE_PACKET_SIZE));
+        }
 
-        // private bool m_sending = false;
+        /// <summary>
+        /// Find the packet number that contains a given byte position
+        /// </summary>
+        /// <param name="bytePosition">Byte position</param>
+        /// <returns>Packet number that contains the given byte position</returns>
+        int GetPacketForBytePosition(int bytePosition)
+        {
+            return ((bytePosition - FIRST_IMAGE_PACKET_SIZE + IMAGE_PACKET_SIZE - 1) / IMAGE_PACKET_SIZE);
+        }
 
         /// <summary>
-        /// This is actually the number of extra packets required to send the texture data!  We always assume
-        /// at least one is required.
+        /// Clamp a given value between a range
         /// </summary>
-        private int NumPackets = 0;
+        /// <param name="value">Value to clamp</param>
+        /// <param name="min">Minimum allowable value</param>
+        /// <param name="max">Maximum allowable value</param>
+        /// <returns>A value inclusively between lower and upper</returns>
+        static int Clamp(int value, int min, int max)
+        {
+            // First we check to see if we're greater than the max
+            value = (value > max) ? max : value;
+
+            // Then we check to see if we're less than the min.
+            value = (value < min) ? min : value;
+
+            // There's no check to see if min > max.
+            return value;
+        }
+    }
+
+    /// <summary>
+    /// A TextureSender handles the process of receiving a texture requested by the client from the
+    /// AssetCache, and then sending that texture back to the client.
+    /// </summary>
+    public class TextureSender : ITextureSender
+    {
+        private static readonly ILog m_log
+            = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+        public bool ImageLoaded = false;
 
         /// <summary>
-        /// Holds the packet number to send next.  In this case, each packet is 1000 bytes long and starts
-        /// at the 600th byte (0th indexed).
+        /// Holds the texture asset to send.
         /// </summary>
-        private int PacketCounter = 0;
+        private AssetBase m_asset;
+        private bool m_cancel = false;
+        private bool m_sending = false;
+        private bool sendFirstPacket = false;
+        private int initialDiscardLevel = 0;
+        private int initialPacketNum = 0;
+        private float initialPriority = 0.0f;
 
-        private int RequestedDiscardLevel = -1;
+        private ImageDownload download;
         private IClientAPI RequestUser;
-        private uint StartPacketNumber = 0;
 
-        public TextureSender(IClientAPI client, int discardLevel, uint packetNumber)
+        public TextureSender(IClientAPI client, int discardLevel, uint packetNumber, float priority)
         {
             RequestUser = client;
-            RequestedDiscardLevel = discardLevel;
-            StartPacketNumber = packetNumber;
+            initialDiscardLevel = discardLevel;
+            initialPacketNum = (int)packetNumber;
+            initialPriority = priority;
         }
 
         #region ITextureSender Members
 
         public bool Cancel
         {
-            get { return false; }
-            set 
-            { 
-                // m_cancel = value; 
-            }
+            get { return m_cancel; }
+            set { m_cancel = value; }
         }
 
         public bool Sending
         {
-            get { return false; }
-            set 
-            { 
-                // m_sending = value; 
-            }
+            get { return m_sending; }
+            set { m_sending = value; }
         }
 
         // See ITextureSender
         public void UpdateRequest(int discardLevel, uint packetNumber)
         {
-            RequestedDiscardLevel = discardLevel;
-            StartPacketNumber = packetNumber;
-            PacketCounter = (int) StartPacketNumber;
+            if (download == null)
+                return;
+
+            lock (download)
+            {
+                if (discardLevel < download.DiscardLevel)
+                    m_log.DebugFormat("Image download {0} is changing from DiscardLevel {1} to {2}",
+                        m_asset.FullID, download.DiscardLevel, discardLevel);
+
+                if (packetNumber != download.CurrentPacket)
+                    m_log.DebugFormat("Image download {0} is changing from Packet {1} to {2}",
+                        m_asset.FullID, download.CurrentPacket, packetNumber);
+
+                download.Update(discardLevel, download.Priority, (int)packetNumber);
+
+                sendFirstPacket = true;
+            }
         }
 
         // See ITextureSender
         public bool SendTexturePacket()
         {
-            //m_log.DebugFormat("[TEXTURE SENDER]: Sending packet for {0}", m_asset.FullID);
-
-            SendPacket();
-            counter++;
-            if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) ||
-                ((RequestedDiscardLevel > 0) && (counter > 50 + (NumPackets / (RequestedDiscardLevel + 1)))))
+            if (download != null && !m_cancel && (sendFirstPacket || download.CurrentPacket <= download.StopPacket))
+            {
+                SendPacket();
+                return false;
+            }
+            else
             {
+                m_sending = false;
+                m_cancel = true;
+                sendFirstPacket = false;
                 return true;
             }
-            return false;
         }
 
         #endregion
@@ -138,76 +220,101 @@ namespace OpenSim.Region.Environment.Modules.Agent.TextureSender
         public void TextureReceived(AssetBase asset)
         {
             m_asset = asset;
-            NumPackets = CalculateNumPackets(asset.Data.Length);
-            PacketCounter = (int) StartPacketNumber;
-            ImageLoaded = true;
-        }
 
-        /// <summary>
-        /// Sends a texture packet to the client.
-        /// </summary>
-        private void SendPacket()
-        {
-            if (PacketCounter <= NumPackets)
+            try
             {
-                if (PacketCounter == 0)
+                OpenMetaverse.AssetTexture texture = new OpenMetaverse.AssetTexture(m_asset.FullID, m_asset.Data);
+                if (texture.DecodeLayerBoundaries())
                 {
-                    if (NumPackets == 0)
+                    bool sane = true;
+
+                    // Sanity check all of the layers
+                    for (int i = 0; i < texture.LayerInfo.Length; i++)
                     {
-                        RequestUser.SendImageFirstPart(1, m_asset.FullID, (uint)m_asset.Data.Length, m_asset.Data, 2);
-                        PacketCounter++;
+                        if (texture.LayerInfo[i].End > texture.AssetData.Length)
+                        {
+                            sane = false;
+                            break;
+                        }
+                    }
+
+                    if (sane)
+                    {
+                        download = new ImageDownload(texture, initialDiscardLevel, initialPriority, initialPacketNum);
+                        ImageLoaded = true;
+                        m_sending = true;
+                        m_cancel = false;
+                        sendFirstPacket = true;
+                        return;
                     }
                     else
                     {
-                        byte[] ImageData1 = new byte[600];
-                        Array.Copy(m_asset.Data, 0, ImageData1, 0, 600);
-
-                        RequestUser.SendImageFirstPart(
-                            (ushort)(NumPackets), m_asset.FullID, (uint)m_asset.Data.Length, ImageData1, 2);
-                        PacketCounter++;
+                        m_log.Error("JPEG2000 texture decoding succeeded, but sanity check failed for " +
+                            m_asset.FullID.ToString());
                     }
                 }
                 else
                 {
-                    int size = m_asset.Data.Length - 600 - (1000 * (PacketCounter - 1));
-                    if (size > 1000) size = 1000;
-                    byte[] imageData = new byte[size];
-                    try
-                    {
-                        Array.Copy(m_asset.Data, 600 + (1000 * (PacketCounter - 1)), imageData, 0, size);
-                    }
-                    catch (ArgumentOutOfRangeException)
-                    {
-                        m_log.Error("[TEXTURE SENDER]: Unable to separate texture into multiple packets: Array bounds failure on asset:" +
-                                    m_asset.FullID.ToString());
-                        return;
-                    }
-                    
-                    RequestUser.SendImageNextPart((ushort)PacketCounter, m_asset.FullID, imageData);
-                    PacketCounter++;
+                    m_log.Error("JPEG2000 texture decoding failed for " + m_asset.FullID.ToString());
                 }
             }
+            catch (Exception ex)
+            {
+                m_log.Error("JPEG2000 texture decoding threw an exception for " + m_asset.FullID.ToString(), ex);
+            }
+
+            ImageLoaded = false;
+            m_sending = false;
+            m_cancel = true;
         }
 
         /// <summary>
-        /// Calculate the number of packets that will be required to send the texture loaded into this sender
-        /// This is actually the number of 1000 byte packets not including an initial 600 byte packet...
+        /// Sends a texture packet to the client.
         /// </summary>
-        /// <param name="length"></param>
-        /// <returns></returns>
-        private int CalculateNumPackets(int length)
+        private void SendPacket()
         {
-            int numPackets = 0;
-
-            if (length > 600)
+            lock (download)
             {
-                //over 600 bytes so split up file
-                int restData = (length - 600);
-                int restPackets = ((restData + 999) / 1000);
-                numPackets = restPackets;
-            }
+                if (sendFirstPacket)
+                {
+                    sendFirstPacket = false;
 
-            return numPackets;
+                    if (m_asset.Data.Length <= ImageDownload.FIRST_IMAGE_PACKET_SIZE)
+                    {
+                        RequestUser.SendImageFirstPart(1, m_asset.FullID, (uint)m_asset.Data.Length, m_asset.Data, 2);
+                        return;
+                    }
+                    else
+                    {
+                        byte[] firstImageData = new byte[ImageDownload.FIRST_IMAGE_PACKET_SIZE];
+                        try { Buffer.BlockCopy(m_asset.Data, 0, firstImageData, 0, ImageDownload.FIRST_IMAGE_PACKET_SIZE); }
+                        catch (Exception)
+                        {
+                            m_log.Error("Texture data copy failed on first packet for " + m_asset.FullID.ToString());
+                            m_cancel = true;
+                            m_sending = false;
+                            return;
+                        }
+                        RequestUser.SendImageFirstPart((ushort)download.TexturePacketCount(), m_asset.FullID, (uint)m_asset.Data.Length, firstImageData, 2);
+                    }
+                }
+
+                int imagePacketSize = (download.CurrentPacket == download.TexturePacketCount() - 1) ?
+                    download.LastPacketSize() : ImageDownload.IMAGE_PACKET_SIZE;
+
+                byte[] imageData = new byte[imagePacketSize];
+                try { Buffer.BlockCopy(m_asset.Data, download.CurrentBytePosition(), imageData, 0, imagePacketSize); }
+                catch (Exception)
+                {
+                    m_log.Error("Texture data copy failed for " + m_asset.FullID.ToString());
+                    m_cancel = true;
+                    m_sending = false;
+                    return;
+                }
+
+                RequestUser.SendImageNextPart((ushort)download.CurrentPacket, m_asset.FullID, imageData);
+                ++download.CurrentPacket;
+            }
         }
     }
 }
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs
index 580982d..ed77b2e 100644
--- a/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs
@@ -30,7 +30,6 @@ using System.Collections;
 using System.Collections.Generic;
 using System.Reflection;
 using OpenMetaverse;
-using OpenMetaverse.Packets;
 using log4net;
 using Nini.Config;
 using Nwc.XmlRpc;
diff --git a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs
index 1e26c91..bcc0d19 100644
--- a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs
@@ -31,7 +31,6 @@ using System.Reflection;
 using System.Text;
 using System.Timers;
 using OpenMetaverse;
-using OpenMetaverse.Packets;
 using log4net;
 using OpenSim.Framework;
 using OpenSim.Framework.Communications.Cache;
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 340dd39..3431309 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -544,11 +544,21 @@ namespace OpenSim.Region.ScriptEngine.XEngine
                             Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
                             Evidence evidence = new Evidence(baseEvidence);
 
-                            m_AppDomains[appDomain] =
+                            AppDomain sandbox =
                                 AppDomain.CreateDomain(
                                     m_Scene.RegionInfo.RegionID.ToString(),
                                     evidence, appSetup);
                             
+                            PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
+                            AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
+                            PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
+                            PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
+                            CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
+                            sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
+                            sandbox.SetAppDomainPolicy(sandboxPolicy);
+
+                            m_AppDomains[appDomain] = sandbox;
+
                             m_AppDomains[appDomain].AssemblyResolve +=
                                 new ResolveEventHandler(
                                     AssemblyResolver.OnAssemblyResolve);
-- 
cgit v1.1