aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Agent/AssetTransaction
diff options
context:
space:
mode:
authorUbitUmarov2015-09-01 11:43:07 +0100
committerUbitUmarov2015-09-01 11:43:07 +0100
commitfb78b182520fc9bb0f971afd0322029c70278ea6 (patch)
treeb4e30d383938fdeef8c92d1d1c2f44bb61d329bd /OpenSim/Region/CoreModules/Agent/AssetTransaction
parentlixo (diff)
parentMantis #7713: fixed bug introduced by 1st MOSES patch. (diff)
downloadopensim-SC-fb78b182520fc9bb0f971afd0322029c70278ea6.zip
opensim-SC-fb78b182520fc9bb0f971afd0322029c70278ea6.tar.gz
opensim-SC-fb78b182520fc9bb0f971afd0322029c70278ea6.tar.bz2
opensim-SC-fb78b182520fc9bb0f971afd0322029c70278ea6.tar.xz
Merge remote-tracking branch 'os/master'
Diffstat (limited to 'OpenSim/Region/CoreModules/Agent/AssetTransaction')
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs184
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs302
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs430
3 files changed, 916 insertions, 0 deletions
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
new file mode 100644
index 0000000..f56d17d
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -0,0 +1,184 @@
1/*
2 * Copyright (c) Contributors, 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 OpenSimulator 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 System.Collections.Generic;
29using System.Reflection;
30using log4net;
31using OpenMetaverse;
32using OpenSim.Framework;
33
34using OpenSim.Region.Framework.Scenes;
35using OpenSim.Services.Interfaces;
36using OpenSim.Region.Framework.Interfaces;
37
38namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
39{
40 /// <summary>
41 /// Manage asset transactions for a single agent.
42 /// </summary>
43 public class AgentAssetTransactions
44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 // Fields
48 private bool m_dumpAssetsToFile;
49 private Scene m_Scene;
50 private Dictionary<UUID, AssetXferUploader> XferUploaders = new Dictionary<UUID, AssetXferUploader>();
51
52 // Methods
53 public AgentAssetTransactions(UUID agentID, Scene scene,
54 bool dumpAssetsToFile)
55 {
56 m_Scene = scene;
57 m_dumpAssetsToFile = dumpAssetsToFile;
58 }
59
60 /// <summary>
61 /// Return the xfer uploader for the given transaction.
62 /// </summary>
63 /// <remarks>
64 /// If an uploader does not already exist for this transaction then it is created, otherwise the existing
65 /// uploader is returned.
66 /// </remarks>
67 /// <param name="transactionID"></param>
68 /// <returns>The asset xfer uploader</returns>
69 public AssetXferUploader RequestXferUploader(UUID transactionID)
70 {
71 AssetXferUploader uploader;
72
73 lock (XferUploaders)
74 {
75 if (!XferUploaders.ContainsKey(transactionID))
76 {
77 uploader = new AssetXferUploader(this, m_Scene, transactionID, m_dumpAssetsToFile);
78
79// m_log.DebugFormat(
80// "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID);
81
82 XferUploaders.Add(transactionID, uploader);
83 }
84 else
85 {
86 uploader = XferUploaders[transactionID];
87 }
88 }
89
90 return uploader;
91 }
92
93 public void HandleXfer(ulong xferID, uint packetID, byte[] data)
94 {
95 AssetXferUploader foundUploader = null;
96
97 lock (XferUploaders)
98 {
99 foreach (AssetXferUploader uploader in XferUploaders.Values)
100 {
101// m_log.DebugFormat(
102// "[AGENT ASSETS TRANSACTIONS]: In HandleXfer, inspect xfer upload with xfer id {0}",
103// uploader.XferID);
104
105 if (uploader.XferID == xferID)
106 {
107 foundUploader = uploader;
108 break;
109 }
110 }
111 }
112
113 if (foundUploader != null)
114 {
115// m_log.DebugFormat(
116// "[AGENT ASSETS TRANSACTIONS]: Found xfer uploader for xfer id {0}, packet id {1}, data length {2}",
117// xferID, packetID, data.Length);
118
119 foundUploader.HandleXferPacket(xferID, packetID, data);
120 }
121 else
122 {
123 // Check if the xfer is a terrain xfer
124 IEstateModule estateModule = m_Scene.RequestModuleInterface<IEstateModule>();
125 if (estateModule != null)
126 {
127 if (estateModule.IsTerrainXfer(xferID))
128 return;
129 }
130
131 m_log.ErrorFormat(
132 "[AGENT ASSET TRANSACTIONS]: Could not find uploader for xfer id {0}, packet id {1}, data length {2}",
133 xferID, packetID, data.Length);
134 }
135 }
136
137 public bool RemoveXferUploader(UUID transactionID)
138 {
139 lock (XferUploaders)
140 {
141 bool removed = XferUploaders.Remove(transactionID);
142
143 if (!removed)
144 m_log.WarnFormat(
145 "[AGENT ASSET TRANSACTIONS]: Received request to remove xfer uploader with transaction ID {0} but none found",
146 transactionID);
147// else
148// m_log.DebugFormat(
149// "[AGENT ASSET TRANSACTIONS]: Removed xfer uploader with transaction ID {0}", transactionID);
150
151 return removed;
152 }
153 }
154
155 public void RequestCreateInventoryItem(IClientAPI remoteClient,
156 UUID transactionID, UUID folderID, uint callbackID,
157 string description, string name, sbyte invType,
158 sbyte type, byte wearableType, uint nextOwnerMask)
159 {
160 AssetXferUploader uploader = RequestXferUploader(transactionID);
161
162 uploader.RequestCreateInventoryItem(
163 remoteClient, folderID, callbackID,
164 description, name, invType, type, wearableType, nextOwnerMask);
165 }
166
167 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient,
168 SceneObjectPart part, UUID transactionID,
169 TaskInventoryItem item)
170 {
171 AssetXferUploader uploader = RequestXferUploader(transactionID);
172
173 uploader.RequestUpdateTaskInventoryItem(remoteClient, item);
174 }
175
176 public void RequestUpdateInventoryItem(IClientAPI remoteClient,
177 UUID transactionID, InventoryItemBase item)
178 {
179 AssetXferUploader uploader = RequestXferUploader(transactionID);
180
181 uploader.RequestUpdateInventoryItem(remoteClient, item);
182 }
183 }
184} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
new file mode 100644
index 0000000..b67c0df
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
@@ -0,0 +1,302 @@
1/*
2 * Copyright (c) Contributors, 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 OpenSimulator 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 System;
29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
32using Nini.Config;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37using Mono.Addins;
38
39namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
40{
41 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AssetTransactionModule")]
42 public class AssetTransactionModule : INonSharedRegionModule,
43 IAgentAssetTransactions
44 {
45// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 protected Scene m_Scene;
48 private bool m_dumpAssetsToFile = false;
49 private int m_levelUpload = 0;
50
51 /// <summary>
52 /// Each agent has its own singleton collection of transactions
53 /// </summary>
54 private Dictionary<UUID, AgentAssetTransactions> AgentTransactions =
55 new Dictionary<UUID, AgentAssetTransactions>();
56
57 #region Region Module interface
58
59 public void Initialise(IConfigSource source)
60 {
61 IConfig sconfig = source.Configs["Startup"];
62 if (sconfig != null)
63 {
64 m_levelUpload = sconfig.GetInt("LevelUpload", 0);
65 }
66 }
67
68 public void AddRegion(Scene scene)
69 {
70 m_Scene = scene;
71 scene.RegisterModuleInterface<IAgentAssetTransactions>(this);
72 scene.EventManager.OnNewClient += NewClient;
73 }
74
75 public void RegionLoaded(Scene scene)
76 {
77 }
78
79 public void RemoveRegion(Scene scene)
80 {
81 }
82
83 public void Close()
84 {
85 }
86
87 public string Name
88 {
89 get { return "AgentTransactionModule"; }
90 }
91
92 public Type ReplaceableInterface
93 {
94 get { return typeof(IAgentAssetTransactions); }
95 }
96
97 #endregion
98
99 public void NewClient(IClientAPI client)
100 {
101 client.OnAssetUploadRequest += HandleUDPUploadRequest;
102 client.OnXferReceive += HandleXfer;
103 }
104
105 #region AgentAssetTransactions
106 /// <summary>
107 /// Get the collection of asset transactions for the given user.
108 /// If one does not already exist, it is created.
109 /// </summary>
110 /// <param name="userID"></param>
111 /// <returns></returns>
112 private AgentAssetTransactions GetUserTransactions(UUID userID)
113 {
114 lock (AgentTransactions)
115 {
116 if (!AgentTransactions.ContainsKey(userID))
117 {
118 AgentAssetTransactions transactions =
119 new AgentAssetTransactions(userID, m_Scene,
120 m_dumpAssetsToFile);
121
122 AgentTransactions.Add(userID, transactions);
123 }
124
125 return AgentTransactions[userID];
126 }
127 }
128
129 /// <summary>
130 /// Remove the given agent asset transactions. This should be called
131 /// when a client is departing from a scene (and hence won't be making
132 /// any more transactions here).
133 /// </summary>
134 /// <param name="userID"></param>
135 public void RemoveAgentAssetTransactions(UUID userID)
136 {
137 // m_log.DebugFormat("Removing agent asset transactions structure for agent {0}", userID);
138
139 lock (AgentTransactions)
140 {
141 AgentTransactions.Remove(userID);
142 }
143 }
144
145 /// <summary>
146 /// Create an inventory item from data that has been received through
147 /// a transaction.
148 /// This is called when new clothing or body parts are created.
149 /// It may also be called in other situations.
150 /// </summary>
151 /// <param name="remoteClient"></param>
152 /// <param name="transactionID"></param>
153 /// <param name="folderID"></param>
154 /// <param name="callbackID"></param>
155 /// <param name="description"></param>
156 /// <param name="name"></param>
157 /// <param name="invType"></param>
158 /// <param name="type"></param>
159 /// <param name="wearableType"></param>
160 /// <param name="nextOwnerMask"></param>
161 public void HandleItemCreationFromTransaction(IClientAPI remoteClient,
162 UUID transactionID, UUID folderID, uint callbackID,
163 string description, string name, sbyte invType,
164 sbyte type, byte wearableType, uint nextOwnerMask)
165 {
166// m_log.DebugFormat(
167// "[TRANSACTIONS MANAGER] Called HandleItemCreationFromTransaction with item {0}", name);
168
169 AgentAssetTransactions transactions =
170 GetUserTransactions(remoteClient.AgentId);
171
172 transactions.RequestCreateInventoryItem(remoteClient, transactionID,
173 folderID, callbackID, description, name, invType, type,
174 wearableType, nextOwnerMask);
175 }
176
177 /// <summary>
178 /// Update an inventory item with data that has been received through a
179 /// transaction.
180 /// </summary>
181 /// <remarks>
182 /// This is called when clothing or body parts are updated (for
183 /// instance, with new textures or colours). It may also be called in
184 /// other situations.
185 /// </remarks>
186 /// <param name="remoteClient"></param>
187 /// <param name="transactionID"></param>
188 /// <param name="item"></param>
189 public void HandleItemUpdateFromTransaction(IClientAPI remoteClient,
190 UUID transactionID, InventoryItemBase item)
191 {
192// m_log.DebugFormat(
193// "[ASSET TRANSACTION MODULE]: Called HandleItemUpdateFromTransaction with item {0}",
194// item.Name);
195
196 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
197
198 transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item);
199 }
200
201 /// <summary>
202 /// Update a task inventory item with data that has been received
203 /// through a transaction.
204 ///
205 /// This is currently called when, for instance, a notecard in a prim
206 /// is saved. The data is sent up through a single AssetUploadRequest.
207 /// A subsequent UpdateTaskInventory then references the transaction
208 /// and comes through this method.
209 /// </summary>
210 /// <param name="remoteClient"></param>
211 /// <param name="part"></param>
212 /// <param name="transactionID"></param>
213 /// <param name="item"></param>
214 public void HandleTaskItemUpdateFromTransaction(
215 IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item)
216 {
217// m_log.DebugFormat(
218// "[ASSET TRANSACTION MODULE]: Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}",
219// item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName);
220
221 AgentAssetTransactions transactions =
222 GetUserTransactions(remoteClient.AgentId);
223
224 transactions.RequestUpdateTaskInventoryItem(remoteClient, part,
225 transactionID, item);
226 }
227
228 /// <summary>
229 /// Request that a client (agent) begin an asset transfer.
230 /// </summary>
231 /// <param name="remoteClient"></param>
232 /// <param name="assetID"></param>
233 /// <param name="transactionID"></param>
234 /// <param name="type"></param>
235 /// <param name="data"></param></param>
236 /// <param name="tempFile"></param>
237 public void HandleUDPUploadRequest(IClientAPI remoteClient,
238 UUID assetID, UUID transactionID, sbyte type, byte[] data,
239 bool storeLocal, bool tempFile)
240 {
241// m_log.DebugFormat(
242// "[ASSET TRANSACTION MODULE]: HandleUDPUploadRequest - assetID: {0}, transaction {1}, type {2}, storeLocal {3}, tempFile {4}, data.Length {5}",
243// assetID, transactionID, type, storeLocal, tempFile, data.Length);
244
245 if (((AssetType)type == AssetType.Texture ||
246 (AssetType)type == AssetType.Sound ||
247 (AssetType)type == AssetType.TextureTGA ||
248 (AssetType)type == AssetType.Animation) &&
249 tempFile == false)
250 {
251 ScenePresence avatar = null;
252 Scene scene = (Scene)remoteClient.Scene;
253 scene.TryGetScenePresence(remoteClient.AgentId, out avatar);
254
255 // check user level
256 if (avatar != null)
257 {
258 if (avatar.UserLevel < m_levelUpload)
259 {
260 remoteClient.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false);
261 return;
262 }
263 }
264
265 // check funds
266 IMoneyModule mm = scene.RequestModuleInterface<IMoneyModule>();
267
268 if (mm != null)
269 {
270 if (!mm.UploadCovered(remoteClient.AgentId, mm.UploadCharge))
271 {
272 remoteClient.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false);
273 return;
274 }
275 }
276 }
277
278 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
279 AssetXferUploader uploader = transactions.RequestXferUploader(transactionID);
280 uploader.StartUpload(remoteClient, assetID, transactionID, type, data, storeLocal, tempFile);
281 }
282
283 /// <summary>
284 /// Handle asset transfer data packets received in response to the
285 /// asset upload request in HandleUDPUploadRequest()
286 /// </summary>
287 /// <param name="remoteClient"></param>
288 /// <param name="xferID"></param>
289 /// <param name="packetID"></param>
290 /// <param name="data"></param>
291 public void HandleXfer(IClientAPI remoteClient, ulong xferID,
292 uint packetID, byte[] data)
293 {
294// m_log.Debug("xferID: " + xferID + " packetID: " + packetID + " data length " + data.Length);
295 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
296
297 transactions.HandleXfer(xferID, packetID, data);
298 }
299
300 #endregion
301 }
302}
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
new file mode 100644
index 0000000..49a96f4
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
@@ -0,0 +1,430 @@
1/*
2 * Copyright (c) Contributors, 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 OpenSimulator 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 System;
29using System.IO;
30using System.Reflection;
31using log4net;
32using OpenMetaverse;
33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Services.Interfaces;
37using PermissionMask = OpenSim.Framework.PermissionMask;
38
39namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
40{
41 public class AssetXferUploader
42 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 /// <summary>
46 /// Upload state.
47 /// </summary>
48 /// <remarks>
49 /// New -> Uploading -> Complete
50 /// </remarks>
51 private enum UploadState
52 {
53 New,
54 Uploading,
55 Complete
56 }
57
58 /// <summary>
59 /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we
60 /// are performing a delayed update.
61 /// </summary>
62 AgentAssetTransactions m_transactions;
63
64 private UploadState m_uploadState = UploadState.New;
65
66 private AssetBase m_asset;
67 private UUID InventFolder = UUID.Zero;
68 private sbyte invType = 0;
69
70 private bool m_createItem;
71 private uint m_createItemCallback;
72
73 private bool m_updateItem;
74 private InventoryItemBase m_updateItemData;
75
76 private bool m_updateTaskItem;
77 private TaskInventoryItem m_updateTaskItemData;
78
79 private string m_description = String.Empty;
80 private bool m_dumpAssetToFile;
81 private string m_name = String.Empty;
82// private bool m_storeLocal;
83 private uint nextPerm = 0;
84 private IClientAPI ourClient;
85
86 private UUID m_transactionID;
87
88 private sbyte type = 0;
89 private byte wearableType = 0;
90 public ulong XferID;
91 private Scene m_Scene;
92
93 /// <summary>
94 /// AssetXferUploader constructor
95 /// </summary>
96 /// <param name='transactions'>/param>
97 /// <param name='scene'></param>
98 /// <param name='transactionID'></param>
99 /// <param name='dumpAssetToFile'>
100 /// If true then when the asset is uploaded it is dumped to a file with the format
101 /// String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat",
102 /// now.Year, now.Month, now.Day, now.Hour, now.Minute,
103 /// now.Second, m_asset.Name, m_asset.Type);
104 /// for debugging purposes.
105 /// </param>
106 public AssetXferUploader(
107 AgentAssetTransactions transactions, Scene scene, UUID transactionID, bool dumpAssetToFile)
108 {
109 m_asset = new AssetBase();
110
111 m_transactions = transactions;
112 m_transactionID = transactionID;
113 m_Scene = scene;
114 m_dumpAssetToFile = dumpAssetToFile;
115 }
116
117 /// <summary>
118 /// Process transfer data received from the client.
119 /// </summary>
120 /// <param name="xferID"></param>
121 /// <param name="packetID"></param>
122 /// <param name="data"></param>
123 /// <returns>True if the transfer is complete, false otherwise or if the xferID was not valid</returns>
124 public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data)
125 {
126// m_log.DebugFormat(
127// "[ASSET XFER UPLOADER]: Received packet {0} for xfer {1} (data length {2})",
128// packetID, xferID, data.Length);
129
130 if (XferID == xferID)
131 {
132 if (m_asset.Data.Length > 1)
133 {
134 byte[] destinationArray = new byte[m_asset.Data.Length + data.Length];
135 Array.Copy(m_asset.Data, 0, destinationArray, 0, m_asset.Data.Length);
136 Array.Copy(data, 0, destinationArray, m_asset.Data.Length, data.Length);
137 m_asset.Data = destinationArray;
138 }
139 else
140 {
141 byte[] buffer2 = new byte[data.Length - 4];
142 Array.Copy(data, 4, buffer2, 0, data.Length - 4);
143 m_asset.Data = buffer2;
144 }
145
146 ourClient.SendConfirmXfer(xferID, packetID);
147
148 if ((packetID & 0x80000000) != 0)
149 {
150 SendCompleteMessage();
151 return true;
152 }
153 }
154
155 return false;
156 }
157
158 /// <summary>
159 /// Start asset transfer from the client
160 /// </summary>
161 /// <param name="remoteClient"></param>
162 /// <param name="assetID"></param>
163 /// <param name="transaction"></param>
164 /// <param name="type"></param>
165 /// <param name="data">
166 /// Optional data. If present then the asset is created immediately with this data
167 /// rather than requesting an upload from the client. The data must be longer than 2 bytes.
168 /// </param>
169 /// <param name="storeLocal"></param>
170 /// <param name="tempFile"></param>
171 public void StartUpload(
172 IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type, byte[] data, bool storeLocal,
173 bool tempFile)
174 {
175// m_log.DebugFormat(
176// "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}",
177// remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length);
178
179 lock (this)
180 {
181 if (m_uploadState != UploadState.New)
182 {
183 m_log.WarnFormat(
184 "[ASSET XFER UPLOADER]: Tried to start upload of asset {0}, transaction {1} for {2} but this is already in state {3}. Aborting.",
185 assetID, transaction, remoteClient.Name, m_uploadState);
186
187 return;
188 }
189
190 m_uploadState = UploadState.Uploading;
191 }
192
193 ourClient = remoteClient;
194
195 m_asset.FullID = assetID;
196 m_asset.Type = type;
197 m_asset.CreatorID = remoteClient.AgentId.ToString();
198 m_asset.Data = data;
199 m_asset.Local = storeLocal;
200 m_asset.Temporary = tempFile;
201
202// m_storeLocal = storeLocal;
203
204 if (m_asset.Data.Length > 2)
205 {
206 SendCompleteMessage();
207 }
208 else
209 {
210 RequestStartXfer();
211 }
212 }
213
214 protected void RequestStartXfer()
215 {
216 XferID = Util.GetNextXferID();
217
218// m_log.DebugFormat(
219// "[ASSET XFER UPLOADER]: Requesting Xfer of asset {0}, type {1}, transfer id {2} from {3}",
220// m_asset.FullID, m_asset.Type, XferID, ourClient.Name);
221
222 ourClient.SendXferRequest(XferID, m_asset.Type, m_asset.FullID, 0, new byte[0]);
223 }
224
225 protected void SendCompleteMessage()
226 {
227 // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create
228 // message from other client UDP.
229 lock (this)
230 {
231 m_uploadState = UploadState.Complete;
232
233 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID);
234
235 if (m_createItem)
236 {
237 CompleteCreateItem(m_createItemCallback);
238 }
239 else if (m_updateItem)
240 {
241 CompleteItemUpdate(m_updateItemData);
242 }
243 else if (m_updateTaskItem)
244 {
245 CompleteTaskItemUpdate(m_updateTaskItemData);
246 }
247// else if (m_storeLocal)
248// {
249// m_Scene.AssetService.Store(m_asset);
250// }
251 }
252
253 m_log.DebugFormat(
254 "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}",
255 m_asset.FullID, m_transactionID);
256
257 if (m_dumpAssetToFile)
258 {
259 DateTime now = DateTime.Now;
260 string filename =
261 String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat",
262 now.Year, now.Month, now.Day, now.Hour, now.Minute,
263 now.Second, m_asset.Name, m_asset.Type);
264 SaveAssetToFile(filename, m_asset.Data);
265 }
266 }
267
268 private void SaveAssetToFile(string filename, byte[] data)
269 {
270 string assetPath = "UserAssets";
271 if (!Directory.Exists(assetPath))
272 {
273 Directory.CreateDirectory(assetPath);
274 }
275 FileStream fs = File.Create(Path.Combine(assetPath, filename));
276 BinaryWriter bw = new BinaryWriter(fs);
277 bw.Write(data);
278 bw.Close();
279 fs.Close();
280 }
281
282 public void RequestCreateInventoryItem(IClientAPI remoteClient,
283 UUID folderID, uint callbackID,
284 string description, string name, sbyte invType,
285 sbyte type, byte wearableType, uint nextOwnerMask)
286 {
287 InventFolder = folderID;
288 m_name = name;
289 m_description = description;
290 this.type = type;
291 this.invType = invType;
292 this.wearableType = wearableType;
293 nextPerm = nextOwnerMask;
294 m_asset.Name = name;
295 m_asset.Description = description;
296 m_asset.Type = type;
297
298 // We must lock to avoid a race with a separate thread uploading the asset.
299 lock (this)
300 {
301 if (m_uploadState == UploadState.Complete)
302 {
303 CompleteCreateItem(callbackID);
304 }
305 else
306 {
307 m_createItem = true; //set flag so the inventory item is created when upload is complete
308 m_createItemCallback = callbackID;
309 }
310 }
311 }
312
313 public void RequestUpdateInventoryItem(IClientAPI remoteClient, InventoryItemBase item)
314 {
315 // We must lock to avoid a race with a separate thread uploading the asset.
316 lock (this)
317 {
318 m_asset.Name = item.Name;
319 m_asset.Description = item.Description;
320 m_asset.Type = (sbyte)item.AssetType;
321
322 // We must always store the item at this point even if the asset hasn't finished uploading, in order
323 // to avoid a race condition when the appearance module retrieves the item to set the asset id in
324 // the AvatarAppearance structure.
325 item.AssetID = m_asset.FullID;
326 if (item.AssetID != UUID.Zero)
327 m_Scene.InventoryService.UpdateItem(item);
328
329 if (m_uploadState == UploadState.Complete)
330 {
331 CompleteItemUpdate(item);
332 }
333 else
334 {
335// m_log.DebugFormat(
336// "[ASSET XFER UPLOADER]: Holding update inventory item request {0} for {1} pending completion of asset xfer for transaction {2}",
337// item.Name, remoteClient.Name, transactionID);
338
339 m_updateItem = true;
340 m_updateItemData = item;
341 }
342 }
343 }
344
345 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, TaskInventoryItem taskItem)
346 {
347 // We must lock to avoid a race with a separate thread uploading the asset.
348 lock (this)
349 {
350 m_asset.Name = taskItem.Name;
351 m_asset.Description = taskItem.Description;
352 m_asset.Type = (sbyte)taskItem.Type;
353 taskItem.AssetID = m_asset.FullID;
354
355 if (m_uploadState == UploadState.Complete)
356 {
357 CompleteTaskItemUpdate(taskItem);
358 }
359 else
360 {
361 m_updateTaskItem = true;
362 m_updateTaskItemData = taskItem;
363 }
364 }
365 }
366
367 /// <summary>
368 /// Store the asset for the given item when it has been uploaded.
369 /// </summary>
370 /// <param name="item"></param>
371 private void CompleteItemUpdate(InventoryItemBase item)
372 {
373// m_log.DebugFormat(
374// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}",
375// m_asset.FullID, item.Name, ourClient.Name);
376
377 m_Scene.AssetService.Store(m_asset);
378
379 m_transactions.RemoveXferUploader(m_transactionID);
380
381 m_Scene.EventManager.TriggerOnNewInventoryItemUploadComplete(ourClient.AgentId, (AssetType)type, m_asset.FullID, m_asset.Name, 0);
382 }
383
384 /// <summary>
385 /// Store the asset for the given task item when it has been uploaded.
386 /// </summary>
387 /// <param name="taskItem"></param>
388 private void CompleteTaskItemUpdate(TaskInventoryItem taskItem)
389 {
390// m_log.DebugFormat(
391// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}",
392// m_asset.FullID, taskItem.Name, ourClient.Name);
393
394 m_Scene.AssetService.Store(m_asset);
395
396 m_transactions.RemoveXferUploader(m_transactionID);
397 }
398
399 private void CompleteCreateItem(uint callbackID)
400 {
401 m_Scene.AssetService.Store(m_asset);
402
403 InventoryItemBase item = new InventoryItemBase();
404 item.Owner = ourClient.AgentId;
405 item.CreatorId = ourClient.AgentId.ToString();
406 item.ID = UUID.Random();
407 item.AssetID = m_asset.FullID;
408 item.Description = m_description;
409 item.Name = m_name;
410 item.AssetType = type;
411 item.InvType = invType;
412 item.Folder = InventFolder;
413 item.BasePermissions = (uint)(PermissionMask.All | PermissionMask.Export);
414 item.CurrentPermissions = item.BasePermissions;
415 item.GroupPermissions=0;
416 item.EveryOnePermissions=0;
417 item.NextPermissions = nextPerm;
418 item.Flags = (uint) wearableType;
419 item.CreationDate = Util.UnixTimeSinceEpoch();
420
421 if (m_Scene.AddInventoryItem(item))
422 ourClient.SendInventoryItemCreateUpdate(item, callbackID);
423 else
424 ourClient.SendAlertMessage("Unable to create inventory item");
425
426 m_transactions.RemoveXferUploader(m_transactionID);
427 }
428
429 }
430} \ No newline at end of file