/Aurora/Modules/Agent/AssetTransaction/AssetTransactionModule.cs
C# | 330 lines | 179 code | 47 blank | 104 comment | 23 complexity | 610fb25f4afec7b649724c68f5359fd9 MD5 | raw file
1/* 2 * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/ 3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * * Neither the name of the Aurora-Sim Project nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28using Aurora.Framework; 29using Aurora.Framework.Modules; 30using Aurora.Framework.PresenceInfo; 31using Aurora.Framework.SceneInfo; 32using Aurora.Framework.Services.ClassHelpers.Inventory; 33using Nini.Config; 34using OpenMetaverse; 35using System; 36using System.Collections.Generic; 37 38namespace Aurora.Modules.Agent.AssetTransaction 39{ 40 public class AssetTransactionModule : INonSharedRegionModule, IAgentAssetTransactions 41 { 42// private static readonly ILog MainConsole.Instance = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 43 44 /// <summary> 45 /// Each agent has its own singleton collection of transactions 46 /// </summary> 47 private readonly Dictionary<UUID, AgentAssetTransactions> AgentTransactions = 48 new Dictionary<UUID, AgentAssetTransactions>(); 49 50 private readonly Dictionary<UUID, IScene> RegisteredScenes = new Dictionary<UUID, IScene>(); 51 private IScene m_scene; 52 53 //[Obsolete] //As long as this is being used to get objects that are not region specific, this is fine to use 54 public IScene MyScene 55 { 56 get { return m_scene; } 57 } 58 59 #region INonSharedRegionModule Members 60 61 public void Initialise(IConfigSource config) 62 { 63 } 64 65 public void AddRegion(IScene scene) 66 { 67 scene.RegisterModuleInterface<IAgentAssetTransactions>(this); 68 69 scene.EventManager.OnNewClient += NewClient; 70 scene.EventManager.OnClosingClient += OnClosingClient; 71 scene.EventManager.OnRemovePresence += OnRemovePresence; 72 73 m_scene = scene; 74 } 75 76 public void RemoveRegion(IScene scene) 77 { 78 scene.UnregisterModuleInterface<IAgentAssetTransactions>(this); 79 80 scene.EventManager.OnNewClient -= NewClient; 81 scene.EventManager.OnClosingClient -= OnClosingClient; 82 scene.EventManager.OnRemovePresence -= OnRemovePresence; 83 84 m_scene = null; 85 } 86 87 public void RegionLoaded(IScene scene) 88 { 89 } 90 91 public Type ReplaceableInterface 92 { 93 get { return null; } 94 } 95 96 public void Close() 97 { 98 } 99 100 public string Name 101 { 102 get { return "AgentTransactionModule"; } 103 } 104 105 #endregion 106 107 public void NewClient(IClientAPI client) 108 { 109 client.OnAssetUploadRequest += HandleUDPUploadRequest; 110 client.OnXferReceive += HandleXfer; 111 } 112 113 private void OnClosingClient(IClientAPI client) 114 { 115 client.OnAssetUploadRequest -= HandleUDPUploadRequest; 116 client.OnXferReceive -= HandleXfer; 117 } 118 119 private void OnRemovePresence(IScenePresence SP) 120 { 121 if (SP != null && !SP.IsChildAgent) 122 RemoveAgentAssetTransactions(SP.UUID); 123 } 124 125 #region AgentAssetTransactions 126 127 /// <summary> 128 /// Remove the given agent asset transactions. This should be called when a client is departing 129 /// from a scene (and hence won't be making any more transactions here). 130 /// </summary> 131 /// <param name="userID"></param> 132 public void RemoveAgentAssetTransactions(UUID userID) 133 { 134 // MainConsole.Instance.DebugFormat("Removing agent asset transactions structure for agent {0}", userID); 135 136 lock (AgentTransactions) 137 { 138 AgentTransactions.Remove(userID); 139 } 140 } 141 142 /// <summary> 143 /// Create an inventory item from data that has been received through a transaction. 144 /// This is called when new clothing or body parts are created. It may also be called in other 145 /// situations. 146 /// </summary> 147 /// <param name="remoteClient"></param> 148 /// <param name="transactionID"></param> 149 /// <param name="folderID"></param> 150 /// <param name="callbackID"></param> 151 /// <param name="description"></param> 152 /// <param name="name"></param> 153 /// <param name="invType"></param> 154 /// <param name="type"></param> 155 /// <param name="wearableType"></param> 156 /// <param name="nextOwnerMask"></param> 157 public void HandleItemCreationFromTransaction(IClientAPI remoteClient, UUID transactionID, UUID folderID, 158 uint callbackID, string description, string name, sbyte invType, 159 sbyte type, byte wearableType, uint nextOwnerMask) 160 { 161 // MainConsole.Instance.DebugFormat( 162 // "[TRANSACTIONS MANAGER] Called HandleItemCreationFromTransaction with item {0}", name); 163 164 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); 165 166 IMonitorModule monitorModule = m_scene.RequestModuleInterface<IMonitorModule>(); 167 if (monitorModule != null) 168 { 169 INetworkMonitor networkMonitor = 170 (INetworkMonitor) 171 monitorModule.GetMonitor(m_scene.RegionInfo.RegionID.ToString(), MonitorModuleHelper.NetworkMonitor); 172 networkMonitor.AddPendingUploads(1); 173 } 174 175 transactions.RequestCreateInventoryItem( 176 remoteClient, transactionID, folderID, callbackID, description, 177 name, invType, type, wearableType, nextOwnerMask); 178 } 179 180 /// <summary> 181 /// Update an inventory item with data that has been received through a transaction. 182 /// This is called when clothing or body parts are updated (for instance, with new textures or 183 /// colours). It may also be called in other situations. 184 /// </summary> 185 /// <param name="remoteClient"></param> 186 /// <param name="transactionID"></param> 187 /// <param name="item"></param> 188 public void HandleItemUpdateFromTransaction(IClientAPI remoteClient, UUID transactionID, 189 InventoryItemBase item) 190 { 191 // MainConsole.Instance.DebugFormat( 192 // "[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}", 193 // item.Name); 194 195 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); 196 197 IMonitorModule monitorModule = m_scene.RequestModuleInterface<IMonitorModule>(); 198 if (monitorModule != null) 199 { 200 INetworkMonitor networkMonitor = 201 (INetworkMonitor) 202 monitorModule.GetMonitor(m_scene.RegionInfo.RegionID.ToString(), MonitorModuleHelper.NetworkMonitor); 203 networkMonitor.AddPendingUploads(1); 204 } 205 206 transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item); 207 } 208 209 /// <summary> 210 /// Update a task inventory item with data that has been received through a transaction. 211 /// This is currently called when, for instance, a notecard in a prim is saved. The data is sent 212 /// up through a single AssetUploadRequest. A subsequent UpdateTaskInventory then references the transaction 213 /// and comes through this method. 214 /// </summary> 215 /// <param name="remoteClient"></param> 216 /// <param name="part"></param> 217 /// <param name="transactionID"></param> 218 /// <param name="item"></param> 219 public void HandleTaskItemUpdateFromTransaction( 220 IClientAPI remoteClient, ISceneChildEntity part, UUID transactionID, TaskInventoryItem item) 221 { 222 // MainConsole.Instance.DebugFormat( 223 // "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0}", 224 // item.Name); 225 226 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); 227 228 IMonitorModule monitorModule = m_scene.RequestModuleInterface<IMonitorModule>(); 229 if (monitorModule != null) 230 { 231 INetworkMonitor networkMonitor = 232 (INetworkMonitor) 233 monitorModule.GetMonitor(m_scene.RegionInfo.RegionID.ToString(), MonitorModuleHelper.NetworkMonitor); 234 networkMonitor.AddPendingUploads(1); 235 } 236 237 transactions.RequestUpdateTaskInventoryItem(remoteClient, part, transactionID, item); 238 } 239 240 /// <summary> 241 /// Get the collection of asset transactions for the given user. If one does not already exist, it 242 /// is created. 243 /// </summary> 244 /// <param name="userID"></param> 245 /// <returns></returns> 246 private AgentAssetTransactions GetUserTransactions(UUID userID) 247 { 248 lock (AgentTransactions) 249 { 250 if (!AgentTransactions.ContainsKey(userID)) 251 { 252 AgentAssetTransactions transactions = new AgentAssetTransactions(userID, m_scene, false); 253 AgentTransactions.Add(userID, transactions); 254 } 255 256 return AgentTransactions[userID]; 257 } 258 } 259 260 /// <summary> 261 /// Request that a client (agent) begin an asset transfer. 262 /// </summary> 263 /// <param name="remoteClient"></param> 264 /// <param name="assetID"></param> 265 /// <param name="transaction"></param> 266 /// <param name="type"></param> 267 /// <param name="data"></param> 268 /// <param name="storeLocal"></param> 269 /// <param name="tempFile"></param> 270 public void HandleUDPUploadRequest(IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type, 271 byte[] data, bool storeLocal, bool tempFile) 272 { 273// MainConsole.Instance.Debug("HandleUDPUploadRequest - assetID: " + assetID.ToString() + " transaction: " + transaction.ToString() + " type: " + type.ToString() + " storelocal: " + storeLocal + " tempFile: " + tempFile); 274 275 if (((AssetType) type == AssetType.Texture || 276 (AssetType) type == AssetType.Sound || 277 (AssetType) type == AssetType.TextureTGA || 278 (AssetType) type == AssetType.Animation) && 279 tempFile == false) 280 { 281 IScene scene = remoteClient.Scene; 282 IMoneyModule mm = scene.RequestModuleInterface<IMoneyModule>(); 283 284 if (mm != null) 285 { 286 if (!mm.Charge(remoteClient, mm.UploadCharge)) 287 { 288 remoteClient.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); 289 return; 290 } 291 } 292 } 293 294 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); 295 296 AssetXferUploader uploader = transactions.RequestXferUploader(transaction); 297 if (uploader != null) 298 { 299 uploader.StartUpload(remoteClient, assetID, transaction, type, data, storeLocal, tempFile); 300 } 301 } 302 303 /// <summary> 304 /// Handle asset transfer data packets received in response to the asset upload request in 305 /// HandleUDPUploadRequest() 306 /// </summary> 307 /// <param name="remoteClient"></param> 308 /// <param name="xferID"></param> 309 /// <param name="packetID"></param> 310 /// <param name="data"></param> 311 public void HandleXfer(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) 312 { 313 //MainConsole.Instance.Debug("xferID: " + xferID + " packetID: " + packetID + " data!"); 314 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); 315 316 IMonitorModule monitorModule = m_scene.RequestModuleInterface<IMonitorModule>(); 317 if (monitorModule != null) 318 { 319 INetworkMonitor networkMonitor = 320 (INetworkMonitor) 321 monitorModule.GetMonitor(m_scene.RegionInfo.RegionID.ToString(), MonitorModuleHelper.NetworkMonitor); 322 networkMonitor.AddPendingUploads(1); 323 } 324 325 transactions.HandleXfer(remoteClient, xferID, packetID, data); 326 } 327 328 #endregion 329 } 330}