diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs new file mode 100644 index 0000000000..27ebfdd79a --- /dev/null +++ b/OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs @@ -0,0 +1,202 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; +using OpenMetaverse; +using OpenMetaverse.Packets; +using OpenSim.Framework; +using OpenSim.Framework.Client; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Statistics; +using OpenSim.Region.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.ClientStack.LindenUDP +{ + public delegate void UploadComplete(string filename, byte[] fileData, IClientAPI remoteClient); + public delegate void UploadAborted(string filename, ulong id, IClientAPI remoteClient); + + public class LLFileTransfer + { + protected IClientAPI m_clientAPI; + + protected Dictionary m_handlers; + protected object m_handlerLock = new object(); + + public LLFileTransfer(IClientAPI clientAPI) + { + m_handlers = new Dictionary(); + m_clientAPI = clientAPI; + + m_clientAPI.OnXferReceive += XferReceive; + m_clientAPI.OnAbortXfer += AbortXferHandler; + } + + public void Close() + { + if (m_clientAPI != null) + { + m_clientAPI.OnXferReceive -= XferReceive; + m_clientAPI.OnAbortXfer -= AbortXferHandler; + m_clientAPI = null; + } + } + + public bool RequestUpload(string clientFileName, UploadComplete uploadCompleteCallback, UploadAborted abortCallback) + { + if ((String.IsNullOrEmpty(clientFileName)) || (uploadCompleteCallback == null)) + { + return false; + } + + XferHandler uploader = new XferHandler(m_clientAPI, clientFileName); + uploader.UploadDone += uploadCompleteCallback; + + if (abortCallback != null) + { + uploader.UploadAborted += abortCallback; + } + + lock (m_handlerLock) + { + if (!m_handlers.ContainsKey(uploader.XferID)) + { + m_handlers.Add(uploader.XferID, uploader); + uploader.RequestStartXfer(m_clientAPI); + return true; + } + else + { + // something went wrong with the xferID allocation + uploader.UploadDone -= uploadCompleteCallback; + if (abortCallback != null) + { + uploader.UploadAborted -= abortCallback; + } + return false; + } + } + } + + protected void AbortXferHandler(IClientAPI remoteClient, ulong xferID) + { + lock (m_handlerLock) + { + if (m_handlers.ContainsKey(xferID)) + { + m_handlers[xferID].AbortUpload(remoteClient); + m_handlers.Remove(xferID); + } + } + } + + protected void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) + { + lock (m_handlerLock) + { + if (m_handlers.ContainsKey(xferID)) + { + m_handlers[xferID].XferReceive(remoteClient, xferID, packetID, data); + } + } + } + } + + public class XferHandler + { + private AssetBase m_asset; + + public event UploadComplete UploadDone; + public event UploadAborted UploadAborted; + + private sbyte type = 0; + + public ulong mXferID; + private UploadComplete handlerUploadDone; + private UploadAborted handlerAbort; + + private bool m_complete = false; + + public bool UploadComplete + { + get { return m_complete; } + } + + public XferHandler(IClientAPI pRemoteClient, string pClientFilename) + { + + m_asset = new AssetBase(); + m_asset.FullID = UUID.Zero; + m_asset.Type = type; + m_asset.Data = new byte[0]; + m_asset.Name = pClientFilename; + m_asset.Description = "empty"; + m_asset.Local = true; + m_asset.Temporary = true; + mXferID = Util.GetNextXferID(); + } + + public ulong XferID + { + get { return mXferID; } + } + + public void RequestStartXfer(IClientAPI pRemoteClient) + { + pRemoteClient.SendXferRequest(mXferID, m_asset.Type, m_asset.FullID, 0, Utils.StringToBytes(m_asset.Name)); + } + + /// + /// Process transfer data received from the client. + /// + /// + /// + /// + public void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) + { + if (mXferID == 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; + } + + remoteClient.SendConfirmXfer(xferID, packetID); + + if ((packetID & 0x80000000) != 0) + { + SendCompleteMessage(remoteClient); + + } + } + } + + protected void SendCompleteMessage(IClientAPI remoteClient) + { + m_complete = true; + handlerUploadDone = UploadDone; + if (handlerUploadDone != null) + { + handlerUploadDone(m_asset.Name, m_asset.Data, remoteClient); + } + } + + public void AbortUpload(IClientAPI remoteClient) + { + handlerAbort = UploadAborted; + if (handlerAbort != null) + { + handlerAbort(m_asset.Name, mXferID, remoteClient); + } + } + } +}