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.
This commit is contained in:
MW
2008-12-15 21:46:57 +00:00
parent 8fffdac7fa
commit 1110ee877f
2 changed files with 135 additions and 36 deletions

View File

@@ -40,18 +40,34 @@ using OpenSim.Region.Environment.Scenes;
namespace OpenSim.Region.ClientStack.LindenUDP
{
/// <summary>
/// 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.
/// </summary>
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<ulong, XferHandler> m_handlers;
protected object m_handlerLock = new object();
protected Dictionary<ulong, XferUploadHandler> m_uploadHandlers;
protected object m_uploadHandlersLock = new object();
/// <summary>
/// Dictionary of files to be sent to clients
/// </summary>
protected static Dictionary<string, byte[]> m_files;
/// <summary>
/// Dictionary of Download Transfers in progess
/// </summary>
protected Dictionary<ulong, XferDownloadHandler> m_downloadHandlers = new Dictionary<ulong, XferDownloadHandler>();
public LLFileTransfer(IClientAPI clientAPI)
{
m_handlers = new Dictionary<ulong, XferHandler>();
m_uploadHandlers = new Dictionary<ulong, XferUploadHandler>();
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()
{
}
/// <summary>
/// Start a transfer
/// </summary>
/// <returns>True if the transfer is complete, false if not</returns>
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;
}
/// <summary>
/// Respond to an ack packet from the client
/// </summary>
/// <param name="packet"></param>
/// <returns>True if the transfer is complete, false otherwise</returns>
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;
}
}
}