/// <summary> /// Request an asset download through the almost deprecated Xfer system /// </summary> /// <param name="filename">Filename of the asset to request</param> /// <param name="deleteOnCompletion">Whether or not to delete the asset /// off the server after it is retrieved</param> /// <param name="useBigPackets">Use large transfer packets or not</param> /// <param name="vFileID">UUID of the file to request, if filename is /// left empty</param> /// <param name="vFileType">Asset type of <code>vFileID</code>, or /// <code>AssetType.Unknown</code> if filename is not empty</param> /// <returns></returns> public ulong RequestAssetXfer(string filename, bool deleteOnCompletion, bool useBigPackets, LLUUID vFileID, AssetType vFileType) { LLUUID uuid = LLUUID.Random(); ulong id = uuid.ToULong(); XferDownload transfer = new XferDownload(); transfer.XferID = id; transfer.ID = new LLUUID(id); // Our dictionary tracks transfers with LLUUIDs, so convert the ulong back transfer.Filename = filename; transfer.VFileID = vFileID; transfer.AssetType = vFileType; // Add this transfer to the dictionary lock (Transfers) Transfers[transfer.ID] = transfer; RequestXferPacket request = new RequestXferPacket(); request.XferID.ID = id; request.XferID.Filename = Helpers.StringToField(filename); request.XferID.FilePath = 4; // "Cache". This is a horrible thing that hardcodes a file path enumeration in to the // protocol. For asset downloads we should only ever need this value request.XferID.DeleteOnCompletion = deleteOnCompletion; request.XferID.UseBigPackets = useBigPackets; request.XferID.VFileID = vFileID; request.XferID.VFileType = (short)vFileType; Client.Network.SendPacket(request); return(id); }
/// <summary> /// Request an asset download through the almost deprecated Xfer system /// </summary> /// <param name="filename">Filename of the asset to request</param> /// <param name="deleteOnCompletion">Whether or not to delete the asset /// off the server after it is retrieved</param> /// <param name="useBigPackets">Use large transfer packets or not</param> /// <param name="vFileID">UUID of the file to request, if filename is /// left empty</param> /// <param name="vFileType">Asset type of <code>vFileID</code>, or /// <code>AssetType.Unknown</code> if filename is not empty</param> /// <returns></returns> public ulong RequestAssetXfer(string filename, bool deleteOnCompletion, bool useBigPackets, LLUUID vFileID, AssetType vFileType) { LLUUID uuid = LLUUID.Random(); ulong id = uuid.GetULong(); XferDownload transfer = new XferDownload(); transfer.XferID = id; transfer.ID = new LLUUID(id); // Our dictionary tracks transfers with LLUUIDs, so convert the ulong back transfer.Filename = filename; transfer.VFileID = vFileID; transfer.AssetType = vFileType; // Add this transfer to the dictionary lock (Transfers) Transfers[transfer.ID] = transfer; RequestXferPacket request = new RequestXferPacket(); request.XferID.ID = id; request.XferID.Filename = Helpers.StringToField(filename); request.XferID.FilePath = 4; // "Cache". This is a horrible thing that hardcodes a file path enumeration in to the // protocol. For asset downloads we should only ever need this value request.XferID.DeleteOnCompletion = deleteOnCompletion; request.XferID.UseBigPackets = useBigPackets; request.XferID.VFileID = vFileID; request.XferID.VFileType = (short)vFileType; Client.Network.SendPacket(request); return id; }
private void SendXferPacketHandler(Packet packet, Simulator simulator) { SendXferPacketPacket xfer = (SendXferPacketPacket)packet; // Lame ulong to LLUUID conversion, please go away Xfer system LLUUID transferID = new LLUUID(xfer.XferID.ID); Transfer transfer; XferDownload download = null; if (Transfers.TryGetValue(transferID, out transfer)) { download = (XferDownload)transfer; // Apply a mask to get rid of the "end of transfer" bit uint packetNum = xfer.XferID.Packet & 0x0FFFFFFF; // Check for out of order packets, possibly indicating a resend if (packetNum != download.PacketNum) { if (packetNum == download.PacketNum - 1) { Client.DebugLog("Resending Xfer download confirmation for packet " + packetNum); SendConfirmXferPacket(download.XferID, packetNum); } else { Client.Log("Out of order Xfer packet in a download, got " + packetNum + " expecting " + download.PacketNum, Helpers.LogLevel.Warning); } return; } if (packetNum == 0) { // This is the first packet received in the download, the first four bytes are a network order size integer download.Size = (int)Helpers.BytesToUIntBig(xfer.DataPacket.Data); download.AssetData = new byte[download.Size]; Buffer.BlockCopy(xfer.DataPacket.Data, 4, download.AssetData, 0, xfer.DataPacket.Data.Length - 4); download.Transferred += xfer.DataPacket.Data.Length - 4; } else { Buffer.BlockCopy(xfer.DataPacket.Data, 0, download.AssetData, 1000 * (int)packetNum, xfer.DataPacket.Data.Length); download.Transferred += xfer.DataPacket.Data.Length; } // Increment the packet number to the packet we are expecting next download.PacketNum++; // Confirm receiving this packet SendConfirmXferPacket(download.XferID, packetNum); if ((xfer.XferID.Packet & 0x80000000) != 0) { // This is the last packet in the transfer if (!String.IsNullOrEmpty(download.Filename)) { Client.DebugLog("Xfer download for asset " + download.Filename + " completed"); } else { Client.DebugLog("Xfer download for asset " + download.VFileID.ToString() + " completed"); } download.Success = true; lock (Transfers) Transfers.Remove(download.ID); if (OnXferReceived != null) { try { OnXferReceived(download); } catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); } } } } }