From 1110ee877ff0cdd17098b5035f147542ccd5ca87 Mon Sep 17 00:00:00 2001 From: MW Date: Mon, 15 Dec 2008 21:46:57 +0000 Subject: [PATCH] More work on moving Xfer file transfer handling code to the Client stack from the various region modules that it is currently in. Still not enabled yet. --- OpenSim/Framework/IClientFileTransfer.cs | 2 +- .../ClientStack/LindenUDP/LLFileTransfer.cs | 169 ++++++++++++++---- 2 files changed, 135 insertions(+), 36 deletions(-) diff --git a/OpenSim/Framework/IClientFileTransfer.cs b/OpenSim/Framework/IClientFileTransfer.cs index 832164ef3f..ac5fc2bdeb 100644 --- a/OpenSim/Framework/IClientFileTransfer.cs +++ b/OpenSim/Framework/IClientFileTransfer.cs @@ -32,7 +32,7 @@ using OpenMetaverse; namespace OpenSim.Framework { - public delegate void UploadComplete(string filename, UUID fileID, byte[] fileData, IClientAPI remoteClient); + public delegate void UploadComplete(string filename, UUID fileID, ulong transferID, byte[] fileData, IClientAPI remoteClient); public delegate void UploadAborted(string filename, UUID fileID, ulong transferID, IClientAPI remoteClient); public interface IClientFileTransfer diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs index 9d7b39ef7b..e5783de2aa 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLFileTransfer.cs @@ -40,18 +40,34 @@ using OpenSim.Region.Environment.Scenes; namespace OpenSim.Region.ClientStack.LindenUDP { + /// + /// A work in progress, to contain the SL specific file transfer code that is currently in various region modules + /// This file currently contains multiple classes that need to be split out into their own files. + /// public class LLFileTransfer : IClientFileTransfer { protected IClientAPI m_clientAPI; /// Dictionary of handlers for uploading files from client /// TODO: Need to add cleanup code to remove handlers that have completed their upload - protected Dictionary m_handlers; - protected object m_handlerLock = new object(); + protected Dictionary m_uploadHandlers; + protected object m_uploadHandlersLock = new object(); + + + /// + /// Dictionary of files to be sent to clients + /// + protected static Dictionary m_files; + + /// + /// Dictionary of Download Transfers in progess + /// + protected Dictionary m_downloadHandlers = new Dictionary(); + public LLFileTransfer(IClientAPI clientAPI) { - m_handlers = new Dictionary(); + m_uploadHandlers = new Dictionary(); m_clientAPI = clientAPI; m_clientAPI.OnXferReceive += XferReceive; @@ -72,10 +88,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if ((String.IsNullOrEmpty(clientFileName)) || (uploadCompleteCallback == null)) { - return false; + return false; } - XferHandler uploader = new XferHandler(m_clientAPI, clientFileName); + XferUploadHandler uploader = new XferUploadHandler(m_clientAPI, clientFileName); return StartUpload(uploader, uploadCompleteCallback, abortCallback); } @@ -87,12 +103,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP return false; } - XferHandler uploader = new XferHandler(m_clientAPI, fileID); + XferUploadHandler uploader = new XferUploadHandler(m_clientAPI, fileID); return StartUpload(uploader, uploadCompleteCallback, abortCallback); } - private bool StartUpload(XferHandler uploader, UploadComplete uploadCompleteCallback, UploadAborted abortCallback) + private bool StartUpload(XferUploadHandler uploader, UploadComplete uploadCompleteCallback, UploadAborted abortCallback) { uploader.UploadDone += uploadCompleteCallback; uploader.UploadDone += RemoveXferHandler; @@ -102,11 +118,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP uploader.UploadAborted += abortCallback; } - lock (m_handlerLock) + lock (m_uploadHandlersLock) { - if (!m_handlers.ContainsKey(uploader.XferID)) + if (!m_uploadHandlers.ContainsKey(uploader.XferID)) { - m_handlers.Add(uploader.XferID, uploader); + m_uploadHandlers.Add(uploader.XferID, uploader); uploader.RequestStartXfer(m_clientAPI); return true; } @@ -126,37 +142,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected void AbortXferHandler(IClientAPI remoteClient, ulong xferID) { - lock (m_handlerLock) + lock (m_uploadHandlersLock) { - if (m_handlers.ContainsKey(xferID)) + if (m_uploadHandlers.ContainsKey(xferID)) { - m_handlers[xferID].AbortUpload(remoteClient); - m_handlers.Remove(xferID); + m_uploadHandlers[xferID].AbortUpload(remoteClient); + m_uploadHandlers.Remove(xferID); } } } protected void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) { - lock (m_handlerLock) + lock (m_uploadHandlersLock) { - if (m_handlers.ContainsKey(xferID)) + if (m_uploadHandlers.ContainsKey(xferID)) { - m_handlers[xferID].XferReceive(remoteClient, xferID, packetID, data); + m_uploadHandlers[xferID].XferReceive(remoteClient, xferID, packetID, data); } } } - protected void RemoveXferHandler(string filename, UUID fileID, byte[] fileData, IClientAPI remoteClient) + protected void RemoveXferHandler(string filename, UUID fileID, ulong transferID, byte[] fileData, IClientAPI remoteClient) { } } - public class XferHandler + public class XferUploadHandler { private AssetBase m_asset; - + public event UploadComplete UploadDone; public event UploadAborted UploadAborted; @@ -173,27 +189,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP get { return m_complete; } } - public XferHandler(IClientAPI pRemoteClient, string pClientFilename) + public XferUploadHandler(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(); + Initialise(UUID.Zero, pClientFilename); } - public XferHandler(IClientAPI pRemoteClient, UUID fileID) + public XferUploadHandler(IClientAPI pRemoteClient, UUID fileID) + { + Initialise(fileID, String.Empty); + } + + private void Initialise(UUID fileID, string fileName) { m_asset = new AssetBase(); m_asset.FullID = fileID; m_asset.Type = type; m_asset.Data = new byte[0]; - m_asset.Name = String.Empty; + m_asset.Name = fileName; m_asset.Description = "empty"; m_asset.Local = true; m_asset.Temporary = true; @@ -207,7 +219,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void RequestStartXfer(IClientAPI pRemoteClient) { - if (!String.IsNullOrEmpty(m_asset.Name) ) + if (!String.IsNullOrEmpty(m_asset.Name)) { pRemoteClient.SendXferRequest(mXferID, m_asset.Type, m_asset.FullID, 0, Utils.StringToBytes(m_asset.Name)); } @@ -257,7 +269,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP handlerUploadDone = UploadDone; if (handlerUploadDone != null) { - handlerUploadDone(m_asset.Name, m_asset.FullID, m_asset.Data, remoteClient); + handlerUploadDone(m_asset.Name, m_asset.FullID, mXferID, m_asset.Data, remoteClient); } } @@ -270,4 +282,91 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } } + + public class XferDownloadHandler + { + public IClientAPI Client; + private bool complete; + public byte[] Data = new byte[0]; + public int DataPointer = 0; + public string FileName = String.Empty; + public uint Packet = 0; + public uint Serial = 1; + public ulong XferID = 0; + + public XferDownloadHandler(string fileName, byte[] data, ulong xferID, IClientAPI client) + { + FileName = fileName; + Data = data; + XferID = xferID; + Client = client; + } + + public XferDownloadHandler() + { + } + + /// + /// Start a transfer + /// + /// True if the transfer is complete, false if not + public bool StartSend() + { + if (Data.Length < 1000) + { + // for now (testing) we only support files under 1000 bytes + byte[] transferData = new byte[Data.Length + 4]; + Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4); + Array.Copy(Data, 0, transferData, 4, Data.Length); + Client.SendXferPacket(XferID, 0 + 0x80000000, transferData); + + complete = true; + } + else + { + byte[] transferData = new byte[1000 + 4]; + Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4); + Array.Copy(Data, 0, transferData, 4, 1000); + Client.SendXferPacket(XferID, 0, transferData); + Packet++; + DataPointer = 1000; + } + + return complete; + } + + /// + /// Respond to an ack packet from the client + /// + /// + /// True if the transfer is complete, false otherwise + public bool AckPacket(uint packet) + { + if (!complete) + { + if ((Data.Length - DataPointer) > 1000) + { + byte[] transferData = new byte[1000]; + Array.Copy(Data, DataPointer, transferData, 0, 1000); + Client.SendXferPacket(XferID, Packet, transferData); + Packet++; + DataPointer += 1000; + } + else + { + byte[] transferData = new byte[Data.Length - DataPointer]; + Array.Copy(Data, DataPointer, transferData, 0, Data.Length - DataPointer); + uint endPacket = Packet |= (uint)0x80000000; + Client.SendXferPacket(XferID, endPacket, transferData); + Packet++; + DataPointer += (Data.Length - DataPointer); + + complete = true; + } + } + + return complete; + } + } + } \ No newline at end of file