From a89d097355526d4dc52a75a9734c6a02c3008ef4 Mon Sep 17 00:00:00 2001 From: Dr Scofield Date: Mon, 9 Feb 2009 09:16:15 +0000 Subject: starting phase 2 of the OpenSim.Region.Environment commit: relocating OpenSim.Region.Environment.Modules.Agent en bloc to OpenSim.Region.CoreModules --- .../AgentAssetTransactionsManager.cs | 231 +++++++++++++++++ .../AssetTransaction/AgentAssetsTransactions.cs | 232 +++++++++++++++++ .../AssetTransaction/AssetTransactionModule.cs | 288 +++++++++++++++++++++ .../Agent/AssetTransaction/AssetXferUploader.cs | 267 +++++++++++++++++++ 4 files changed, 1018 insertions(+) create mode 100644 OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetTransactionsManager.cs create mode 100644 OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs create mode 100644 OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs create mode 100644 OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs (limited to 'OpenSim/Region/CoreModules/Agent/AssetTransaction') diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetTransactionsManager.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetTransactionsManager.cs new file mode 100644 index 0000000..2be1eaa --- /dev/null +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetTransactionsManager.cs @@ -0,0 +1,231 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Collections.Generic; +//using System.Reflection; +//using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Region.CoreModules.Agent.AssetTransaction +{ + /* + public class AgentAssetTransactionsManager + { + //private static readonly ILog m_log + // = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Each agent has its own singleton collection of transactions + /// + private Dictionary AgentTransactions = + new Dictionary(); + + /// + /// Should we dump uploaded assets to the filesystem? + /// + private bool m_dumpAssetsToFile; + + public Scene MyScene; + + public AgentAssetTransactionsManager(Scene scene, bool dumpAssetsToFile) + { + MyScene = scene; + m_dumpAssetsToFile = dumpAssetsToFile; + } + + /// + /// Get the collection of asset transactions for the given user. If one does not already exist, it + /// is created. + /// + /// + /// + private AgentAssetTransactions GetUserTransactions(UUID userID) + { + lock (AgentTransactions) + { + if (!AgentTransactions.ContainsKey(userID)) + { + AgentAssetTransactions transactions = null; + //= new AgentAssetTransactions(userID, this, m_dumpAssetsToFile); + AgentTransactions.Add(userID, transactions); + } + + return AgentTransactions[userID]; + } + } + + /// + /// Remove the given agent asset transactions. This should be called when a client is departing + /// from a scene (and hence won't be making any more transactions here). + /// + /// + public void RemoveAgentAssetTransactions(UUID userID) + { + // m_log.DebugFormat("Removing agent asset transactions structure for agent {0}", userID); + + lock (AgentTransactions) + { + AgentTransactions.Remove(userID); + } + } + + /// + /// Create an inventory item from data that has been received through a transaction. + /// + /// This is called when new clothing or body parts are created. It may also be called in other + /// situations. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public void HandleItemCreationFromTransaction(IClientAPI remoteClient, UUID transactionID, UUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte type, byte wearableType, uint nextOwnerMask) + { +// m_log.DebugFormat( +// "[TRANSACTIONS MANAGER] Called HandleItemCreationFromTransaction with item {0}", name); + + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + transactions.RequestCreateInventoryItem( + remoteClient, transactionID, folderID, callbackID, description, + name, invType, type, wearableType, nextOwnerMask); + } + + /// + /// Update an inventory item with data that has been received through a transaction. + /// + /// This is called when clothing or body parts are updated (for instance, with new textures or + /// colours). It may also be called in other situations. + /// + /// + /// + /// + public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, UUID transactionID, + InventoryItemBase item) + { +// m_log.DebugFormat( +// "[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}", +// item.Name); + + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item); + } + + /// + /// Update a task inventory item with data that has been received through a transaction. + /// + /// This is currently called when, for instance, a notecard in a prim is saved. The data is sent + /// up through a single AssetUploadRequest. A subsequent UpdateTaskInventory then references the transaction + /// and comes through this method. + /// + /// + /// + /// + public void HandleTaskItemUpdateFromTransaction( + IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) + { +// m_log.DebugFormat( +// "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0}", +// item.Name); + + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + transactions.RequestUpdateTaskInventoryItem(remoteClient, part, transactionID, item); + } + + /// + /// Request that a client (agent) begin an asset transfer. + /// + /// + /// + /// + /// + /// + /// + public void HandleUDPUploadRequest(IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type, + byte[] data, bool storeLocal, bool tempFile) + { + //System.Console.WriteLine("HandleUDPUploadRequest - assetID: " + assetID.ToString() + " transaction: " + transaction.ToString() + " type: " + type.ToString() + " storelocal: " + storeLocal + " tempFile: " + tempFile); + if (((AssetType)type == AssetType.Texture || + (AssetType)type == AssetType.Sound || + (AssetType)type == AssetType.TextureTGA || + (AssetType)type == AssetType.Animation) && + tempFile == false) + { + Scene scene = (Scene)remoteClient.Scene; + IMoneyModule mm = scene.RequestModuleInterface(); + + if (mm != null) + { + if (!mm.UploadCovered(remoteClient)) + { + remoteClient.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); + return; + } + } + } + + //Console.WriteLine("asset upload of " + assetID); + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + AssetXferUploader uploader = transactions.RequestXferUploader(transaction); + if (uploader != null) + { + uploader.Initialise(remoteClient, assetID, transaction, type, data, storeLocal, tempFile); + } + } + + /// + /// Handle asset transfer data packets received in response to the asset upload request in + /// HandleUDPUploadRequest() + /// + /// + /// + /// + /// + public void HandleXfer(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) + { + //System.Console.WriteLine("xferID: " + xferID + " packetID: " + packetID + " data!"); + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + transactions.HandleXfer(xferID, packetID, data); + } + } + */ +} diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs new file mode 100644 index 0000000..b4dbaa1 --- /dev/null +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs @@ -0,0 +1,232 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Framework.Communications.Cache; + +namespace OpenSim.Region.CoreModules.Agent.AssetTransaction +{ + /// + /// Manage asset transactions for a single agent. + /// + public class AgentAssetTransactions + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + // Fields + private bool m_dumpAssetsToFile; + public AssetTransactionModule Manager; + public UUID UserID; + public Dictionary XferUploaders = new Dictionary(); + + // Methods + public AgentAssetTransactions(UUID agentID, AssetTransactionModule manager, bool dumpAssetsToFile) + { + UserID = agentID; + Manager = manager; + m_dumpAssetsToFile = dumpAssetsToFile; + } + + public AssetXferUploader RequestXferUploader(UUID transactionID) + { + if (!XferUploaders.ContainsKey(transactionID)) + { + AssetXferUploader uploader = new AssetXferUploader(this, m_dumpAssetsToFile); + + lock (XferUploaders) + { + XferUploaders.Add(transactionID, uploader); + } + + return uploader; + } + return null; + } + + public void HandleXfer(ulong xferID, uint packetID, byte[] data) + { + lock (XferUploaders) + { + foreach (AssetXferUploader uploader in XferUploaders.Values) + { + if (uploader.XferID == xferID) + { + uploader.HandleXferPacket(xferID, packetID, data); + break; + } + } + } + } + + public void RequestCreateInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte type, byte wearableType, uint nextOwnerMask) + { + if (XferUploaders.ContainsKey(transactionID)) + { + XferUploaders[transactionID].RequestCreateInventoryItem(remoteClient, transactionID, folderID, + callbackID, description, name, invType, type, + wearableType, nextOwnerMask); + } + } + + + + /// + /// Get an uploaded asset. If the data is successfully retrieved, the transaction will be removed. + /// + /// + /// The asset if the upload has completed, null if it has not. + public AssetBase GetTransactionAsset(UUID transactionID) + { + if (XferUploaders.ContainsKey(transactionID)) + { + AssetXferUploader uploader = XferUploaders[transactionID]; + AssetBase asset = uploader.GetAssetData(); + + lock (XferUploaders) + { + XferUploaders.Remove(transactionID); + } + + return asset; + } + + return null; + } + + //private void CreateItemFromUpload(AssetBase asset, IClientAPI ourClient, UUID inventoryFolderID, uint nextPerms, uint wearableType) + //{ + // Manager.MyScene.CommsManager.AssetCache.AddAsset(asset); + // CachedUserInfo userInfo = Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails( + // ourClient.AgentId); + + // if (userInfo != null) + // { + // InventoryItemBase item = new InventoryItemBase(); + // item.Owner = ourClient.AgentId; + // item.Creator = ourClient.AgentId; + // item.ID = UUID.Random(); + // item.AssetID = asset.FullID; + // item.Description = asset.Description; + // item.Name = asset.Name; + // item.AssetType = asset.Type; + // item.InvType = asset.Type; + // item.Folder = inventoryFolderID; + // item.BasePermissions = 0x7fffffff; + // item.CurrentPermissions = 0x7fffffff; + // item.EveryOnePermissions = 0; + // item.NextPermissions = nextPerms; + // item.Flags = wearableType; + // item.CreationDate = Util.UnixTimeSinceEpoch(); + + // userInfo.AddItem(item); + // ourClient.SendInventoryItemCreateUpdate(item); + // } + // else + // { + // m_log.ErrorFormat( + // "[ASSET TRANSACTIONS]: Could not find user {0} for inventory item creation", + // ourClient.AgentId); + // } + //} + + public void RequestUpdateTaskInventoryItem( + IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) + { + if (XferUploaders.ContainsKey(transactionID)) + { + AssetBase asset = XferUploaders[transactionID].GetAssetData(); + if (asset != null) + { + m_log.DebugFormat( + "[ASSET TRANSACTIONS]: Updating task item {0} in {1} with asset in transaction {2}", + item.Name, part.Name, transactionID); + + asset.Metadata.Name = item.Name; + asset.Metadata.Description = item.Description; + asset.Metadata.Type = (sbyte)item.Type; + item.AssetID = asset.Metadata.FullID; + + Manager.MyScene.CommsManager.AssetCache.AddAsset(asset); + + if (part.Inventory.UpdateInventoryItem(item)) + part.GetProperties(remoteClient); + } + } + } + + + public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, + InventoryItemBase item) + { + if (XferUploaders.ContainsKey(transactionID)) + { + CachedUserInfo userInfo = Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails( + remoteClient.AgentId); + + if (userInfo != null) + { + UUID assetID = UUID.Combine(transactionID, remoteClient.SecureSessionId); + + AssetBase asset + = Manager.MyScene.CommsManager.AssetCache.GetAsset( + assetID, (item.AssetType == (int)AssetType.Texture ? true : false)); + + if (asset == null) + { + asset = GetTransactionAsset(transactionID); + } + + if (asset != null && asset.Metadata.FullID == assetID) + { + // Assets never get updated, new ones get created + asset.Metadata.FullID = UUID.Random(); + asset.Metadata.Name = item.Name; + asset.Metadata.Description = item.Description; + asset.Metadata.Type = (sbyte)item.AssetType; + item.AssetID = asset.Metadata.FullID; + + Manager.MyScene.CommsManager.AssetCache.AddAsset(asset); + } + + userInfo.UpdateItem(item); + } + else + { + m_log.ErrorFormat( + "[ASSET TRANSACTIONS]: Could not find user {0} for inventory item update", + remoteClient.AgentId); + } + } + } + } +} diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs new file mode 100644 index 0000000..77dfd44 --- /dev/null +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs @@ -0,0 +1,288 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using OpenMetaverse; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Agent.AssetTransaction +{ + public class AssetTransactionModule : IRegionModule, IAgentAssetTransactions + { + private readonly Dictionary RegisteredScenes = new Dictionary(); + private bool m_dumpAssetsToFile = false; + private Scene m_scene = null; + + public Scene MyScene + { + get{ return m_scene;} + } + + /// + /// Each agent has its own singleton collection of transactions + /// + private Dictionary AgentTransactions = + new Dictionary(); + + + public AssetTransactionModule() + { + // System.Console.WriteLine("creating AgentAssetTransactionModule"); + } + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) + { + // System.Console.WriteLine("initialising AgentAssetTransactionModule"); + RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); + scene.RegisterModuleInterface(this); + + scene.EventManager.OnNewClient += NewClient; + } + + if (m_scene == null) + { + m_scene = scene; + if (config.Configs["StandAlone"] != null) + { + try + { + m_dumpAssetsToFile = config.Configs["StandAlone"].GetBoolean("dump_assets_to_file", false); + } + catch (Exception) + { + } + } + else + { + } + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "AgentTransactionModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + public void NewClient(IClientAPI client) + { + client.OnAssetUploadRequest += HandleUDPUploadRequest; + client.OnXferReceive += HandleXfer; + } + + #region AgentAssetTransactions + /// + /// Get the collection of asset transactions for the given user. If one does not already exist, it + /// is created. + /// + /// + /// + private AgentAssetTransactions GetUserTransactions(UUID userID) + { + lock (AgentTransactions) + { + if (!AgentTransactions.ContainsKey(userID)) + { + AgentAssetTransactions transactions = new AgentAssetTransactions(userID, this, m_dumpAssetsToFile); + AgentTransactions.Add(userID, transactions); + } + + return AgentTransactions[userID]; + } + } + + /// + /// Remove the given agent asset transactions. This should be called when a client is departing + /// from a scene (and hence won't be making any more transactions here). + /// + /// + public void RemoveAgentAssetTransactions(UUID userID) + { + // m_log.DebugFormat("Removing agent asset transactions structure for agent {0}", userID); + + lock (AgentTransactions) + { + AgentTransactions.Remove(userID); + } + } + + /// + /// Create an inventory item from data that has been received through a transaction. + /// + /// This is called when new clothing or body parts are created. It may also be called in other + /// situations. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public void HandleItemCreationFromTransaction(IClientAPI remoteClient, UUID transactionID, UUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte type, byte wearableType, uint nextOwnerMask) + { + // m_log.DebugFormat( + // "[TRANSACTIONS MANAGER] Called HandleItemCreationFromTransaction with item {0}", name); + + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + transactions.RequestCreateInventoryItem( + remoteClient, transactionID, folderID, callbackID, description, + name, invType, type, wearableType, nextOwnerMask); + } + + /// + /// Update an inventory item with data that has been received through a transaction. + /// + /// This is called when clothing or body parts are updated (for instance, with new textures or + /// colours). It may also be called in other situations. + /// + /// + /// + /// + public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, UUID transactionID, + InventoryItemBase item) + { + // m_log.DebugFormat( + // "[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}", + // item.Name); + + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item); + } + + /// + /// Update a task inventory item with data that has been received through a transaction. + /// + /// This is currently called when, for instance, a notecard in a prim is saved. The data is sent + /// up through a single AssetUploadRequest. A subsequent UpdateTaskInventory then references the transaction + /// and comes through this method. + /// + /// + /// + /// + public void HandleTaskItemUpdateFromTransaction( + IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) + { + // m_log.DebugFormat( + // "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0}", + // item.Name); + + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + transactions.RequestUpdateTaskInventoryItem(remoteClient, part, transactionID, item); + } + + /// + /// Request that a client (agent) begin an asset transfer. + /// + /// + /// + /// + /// + /// + /// + public void HandleUDPUploadRequest(IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type, + byte[] data, bool storeLocal, bool tempFile) + { + //System.Console.WriteLine("HandleUDPUploadRequest - assetID: " + assetID.ToString() + " transaction: " + transaction.ToString() + " type: " + type.ToString() + " storelocal: " + storeLocal + " tempFile: " + tempFile); + if (((AssetType)type == AssetType.Texture || + (AssetType)type == AssetType.Sound || + (AssetType)type == AssetType.TextureTGA || + (AssetType)type == AssetType.Animation) && + tempFile == false) + { + Scene scene = (Scene)remoteClient.Scene; + IMoneyModule mm = scene.RequestModuleInterface(); + + if (mm != null) + { + if (!mm.UploadCovered(remoteClient)) + { + remoteClient.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); + return; + } + } + } + + //Console.WriteLine("asset upload of " + assetID); + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + AssetXferUploader uploader = transactions.RequestXferUploader(transaction); + if (uploader != null) + { + uploader.Initialise(remoteClient, assetID, transaction, type, data, storeLocal, tempFile); + } + } + + /// + /// Handle asset transfer data packets received in response to the asset upload request in + /// HandleUDPUploadRequest() + /// + /// + /// + /// + /// + public void HandleXfer(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) + { + //System.Console.WriteLine("xferID: " + xferID + " packetID: " + packetID + " data!"); + AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); + + transactions.HandleXfer(xferID, packetID, data); + } + + #endregion + } +} diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs new file mode 100644 index 0000000..aef2664 --- /dev/null +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs @@ -0,0 +1,267 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.IO; +using System.Reflection; +using log4net; +using OpenMetaverse; +using OpenMetaverse.Packets; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Agent.AssetTransaction +{ + public class AssetXferUploader + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private AssetBase m_asset; + private UUID InventFolder = UUID.Zero; + private sbyte invType = 0; + private bool m_createItem = false; + private string m_description = String.Empty; + private bool m_dumpAssetToFile; + private bool m_finished = false; + private string m_name = String.Empty; + private bool m_storeLocal; + private AgentAssetTransactions m_userTransactions; + private uint nextPerm = 0; + private IClientAPI ourClient; + private UUID TransactionID = UUID.Zero; + private sbyte type = 0; + private byte wearableType = 0; + public ulong XferID; + + public AssetXferUploader(AgentAssetTransactions transactions, bool dumpAssetToFile) + { + m_userTransactions = transactions; + m_dumpAssetToFile = dumpAssetToFile; + } + + /// + /// Process transfer data received from the client. + /// + /// + /// + /// + /// True if the transfer is complete, false otherwise or if the xferID was not valid + public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data) + { + if (XferID == xferID) + { + if (m_asset.Data.Length > 1) + { + byte[] destinationArray = new byte[m_asset.Data.Length + data.Length]; + Array.Copy(m_asset.Data, 0, destinationArray, 0, m_asset.Data.Length); + Array.Copy(data, 0, destinationArray, m_asset.Data.Length, data.Length); + m_asset.Data = destinationArray; + } + else + { + byte[] buffer2 = new byte[data.Length - 4]; + Array.Copy(data, 4, buffer2, 0, data.Length - 4); + m_asset.Data = buffer2; + } + + ourClient.SendConfirmXfer(xferID, packetID); + + if ((packetID & 0x80000000) != 0) + { + SendCompleteMessage(); + return true; + } + } + + return false; + } + + /// + /// Initialise asset transfer from the client + /// + /// + /// + /// + /// True if the transfer is complete, false otherwise + public bool Initialise(IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type, byte[] data, + bool storeLocal, bool tempFile) + { + ourClient = remoteClient; + m_asset = new AssetBase(); + m_asset.Metadata.FullID = assetID; + m_asset.Metadata.Type = type; + m_asset.Data = data; + m_asset.Metadata.Name = "blank"; + m_asset.Metadata.Description = "empty"; + m_asset.Metadata.Local = storeLocal; + m_asset.Metadata.Temporary = tempFile; + + TransactionID = transaction; + m_storeLocal = storeLocal; + + if (m_asset.Data.Length > 2) + { + SendCompleteMessage(); + return true; + } + else + { + RequestStartXfer(); + } + + return false; + } + + protected void RequestStartXfer() + { + XferID = Util.GetNextXferID(); + ourClient.SendXferRequest(XferID, m_asset.Metadata.Type, m_asset.Metadata.FullID, 0, new byte[0]); + } + + protected void SendCompleteMessage() + { + ourClient.SendAssetUploadCompleteMessage(m_asset.Metadata.Type, true, m_asset.Metadata.FullID); + + m_finished = true; + if (m_createItem) + { + DoCreateItem(); + } + else if (m_storeLocal) + { + m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(m_asset); + } + + m_log.DebugFormat("[ASSET TRANSACTIONS]: Uploaded asset data for transaction {0}", TransactionID); + + if (m_dumpAssetToFile) + { + DateTime now = DateTime.Now; + string filename = + String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat", now.Year, now.Month, now.Day, + now.Hour, now.Minute, now.Second, m_asset.Metadata.Name, m_asset.Metadata.Type); + SaveAssetToFile(filename, m_asset.Data); + } + } + + private void SaveAssetToFile(string filename, byte[] data) + { + string assetPath = "UserAssets"; + if (!Directory.Exists(assetPath)) + { + Directory.CreateDirectory(assetPath); + } + FileStream fs = File.Create(Path.Combine(assetPath, filename)); + BinaryWriter bw = new BinaryWriter(fs); + bw.Write(data); + bw.Close(); + fs.Close(); + } + + public void RequestCreateInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte type, byte wearableType, uint nextOwnerMask) + { + if (TransactionID == transactionID) + { + InventFolder = folderID; + m_name = name; + m_description = description; + this.type = type; + this.invType = invType; + this.wearableType = wearableType; + nextPerm = nextOwnerMask; + m_asset.Metadata.Name = name; + m_asset.Metadata.Description = description; + m_asset.Metadata.Type = type; + + if (m_finished) + { + DoCreateItem(); + } + else + { + m_createItem = true; //set flag so the inventory item is created when upload is complete + } + } + } + + + private void DoCreateItem() + { + m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(m_asset); + CachedUserInfo userInfo = + m_userTransactions.Manager.MyScene.CommsManager.UserProfileCacheService.GetUserDetails( + ourClient.AgentId); + + if (userInfo != null) + { + InventoryItemBase item = new InventoryItemBase(); + item.Owner = ourClient.AgentId; + item.Creator = ourClient.AgentId; + item.ID = UUID.Random(); + item.AssetID = m_asset.Metadata.FullID; + item.Description = m_description; + item.Name = m_name; + item.AssetType = type; + item.InvType = invType; + item.Folder = InventFolder; + item.BasePermissions = 0x7fffffff; + item.CurrentPermissions = 0x7fffffff; + item.GroupPermissions=0; + item.EveryOnePermissions=0; + item.NextPermissions = nextPerm; + item.Flags = (uint) wearableType; + item.CreationDate = Util.UnixTimeSinceEpoch(); + + userInfo.AddItem(item); + ourClient.SendInventoryItemCreateUpdate(item); + } + else + { + m_log.ErrorFormat( + "[ASSET TRANSACTIONS]: Could not find user {0} for inventory item creation", + ourClient.AgentId); + } + } + + /// + /// Get the asset data uploaded in this transfer. + /// + /// null if the asset has not finished uploading + public AssetBase GetAssetData() + { + if (m_finished) + { + return m_asset; + } + + return null; + } + } +} -- cgit v1.1