/// <summary>Process an incoming packet and raise the appropriate events</summary> /// <param name="sender">The sender</param> /// <param name="e">The EventArgs object containing the packet data</param> protected void TransferPacketHandler(object sender, PacketReceivedEventArgs e) { TransferPacketPacket asset = (TransferPacketPacket)e.Packet; Transfer transfer; AssetDownload download; if (Transfers.TryGetValue(asset.TransferData.TransferID, out transfer)) { download = (AssetDownload)transfer; if (download.Size == 0) { Logger.DebugLog("TransferPacket received ahead of the transfer header, blocking...", Client); // We haven't received the header yet, block until it's received or times out download.HeaderReceivedEvent.WaitOne(TRANSFER_HEADER_TIMEOUT, false); if (download.Size == 0) { Logger.Log("Timed out while waiting for the asset header to download for " + download.ID.ToString(), Helpers.LogLevel.Warning, Client); // Abort the transfer TransferAbortPacket abort = new TransferAbortPacket(); abort.TransferInfo.ChannelType = (int)download.Channel; abort.TransferInfo.TransferID = download.ID; Client.Network.SendPacket(abort, download.Simulator); download.Success = false; lock (Transfers) Transfers.Remove(download.ID); // Fire the event with our transfer that contains Success = false if (download.Callback != null) { try { download.Callback(download, null); } catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client, ex); } } return; } } // This assumes that every transfer packet except the last one is exactly 1000 bytes, // hopefully that is a safe assumption to make try { Buffer.BlockCopy(asset.TransferData.Data, 0, download.AssetData, 1000 * asset.TransferData.Packet, asset.TransferData.Data.Length); download.Transferred += asset.TransferData.Data.Length; } catch (ArgumentException) { Logger.Log(String.Format("TransferPacket handling failed. TransferData.Data.Length={0}, AssetData.Length={1}, TransferData.Packet={2}", asset.TransferData.Data.Length, download.AssetData.Length, asset.TransferData.Packet), Helpers.LogLevel.Error); return; } //Client.DebugLog(String.Format("Transfer packet {0}, received {1}/{2}/{3} bytes for asset {4}", // asset.TransferData.Packet, asset.TransferData.Data.Length, transfer.Transferred, transfer.Size, // transfer.AssetID.ToString())); // Check if we downloaded the full asset if (download.Transferred >= download.Size) { Logger.DebugLog("Transfer for asset " + download.AssetID.ToString() + " completed", Client); download.Success = true; lock (Transfers) Transfers.Remove(download.ID); // Cache successful asset download Cache.SaveAssetToCache(download.AssetID, download.AssetData); if (download.Callback != null) { try { download.Callback(download, WrapAsset(download)); } catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client, ex); } } } } }
/// <summary>Process an incoming packet and raise the appropriate events</summary> /// <param name="sender">The sender</param> /// <param name="e">The EventArgs object containing the packet data</param> protected void TransferPacketHandler(object sender, PacketReceivedEventArgs e) { TransferPacketPacket asset = (TransferPacketPacket)e.Packet; Transfer transfer; if (Transfers.TryGetValue(asset.TransferData.TransferID, out transfer)) { AssetDownload download = (AssetDownload)transfer; if (download.Size == 0) { Logger.DebugLog("TransferPacket received ahead of the transfer header, blocking...", Client); // We haven't received the header yet, block until it's received or times out download.HeaderReceivedEvent.WaitOne(TRANSFER_HEADER_TIMEOUT, false); if (download.Size == 0) { Logger.Log("Timed out while waiting for the asset header to download for " + download.ID.ToString(), Helpers.LogLevel.Warning, Client); // Abort the transfer TransferAbortPacket abort = new TransferAbortPacket(); abort.TransferInfo.ChannelType = (int)download.Channel; abort.TransferInfo.TransferID = download.ID; Client.Network.SendPacket(abort, download.Simulator); download.Success = false; lock (Transfers) Transfers.Remove(download.ID); // Fire the event with our transfer that contains Success = false if (download.Callback != null) { try { download.Callback(download, null); } catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client, ex); } } return; } } // If packets arrive out of order, we add them to the out of order packet directory // until all previous packets have arrived try { if (download.nextPacket == asset.TransferData.Packet) { byte[] data = asset.TransferData.Data; do { Buffer.BlockCopy(data, 0, download.AssetData, download.Transferred, data.Length); download.Transferred += data.Length; download.nextPacket++; } while (download.outOfOrderPackets.TryGetValue(download.nextPacket, out data)); } else { //Logger.Log(string.Format("Fixing out of order packet {0} when expecting {1}!", asset.TransferData.Packet, download.nextPacket), Helpers.LogLevel.Debug); download.outOfOrderPackets.Add(asset.TransferData.Packet, asset.TransferData.Data); } } catch (ArgumentException) { Logger.Log(String.Format("TransferPacket handling failed. TransferData.Data.Length={0}, AssetData.Length={1}, TransferData.Packet={2}", asset.TransferData.Data.Length, download.AssetData.Length, asset.TransferData.Packet), Helpers.LogLevel.Error); return; } //Client.DebugLog(String.Format("Transfer packet {0}, received {1}/{2}/{3} bytes for asset {4}", // asset.TransferData.Packet, asset.TransferData.Data.Length, transfer.Transferred, transfer.Size, // transfer.AssetID.ToString())); // Check if we downloaded the full asset if (download.Transferred >= download.Size) { Logger.DebugLog("Transfer for asset " + download.AssetID.ToString() + " completed", Client); download.Success = true; lock (Transfers) Transfers.Remove(download.ID); // Cache successful asset download Cache.SaveAssetToCache(download.AssetID, download.AssetData); if (download.Callback != null) { try { download.Callback(download, WrapAsset(download)); } catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client, ex); } } } } }
private void TransferPacketHandler(Packet packet, Simulator simulator) { TransferPacketPacket asset = (TransferPacketPacket)packet; Transfer transfer; AssetDownload download; if (Transfers.TryGetValue(asset.TransferData.TransferID, out transfer)) { download = (AssetDownload)transfer; if (download.Size == 0) { Client.DebugLog("TransferPacket received ahead of the transfer header, blocking..."); // We haven't received the header yet, block until it's received or times out download.HeaderReceivedEvent.WaitOne(1000 * 20, false); if (download.Size == 0) { Client.Log("Timed out while waiting for the asset header to download for " + download.ID.ToString(), Helpers.LogLevel.Warning); // Abort the transfer TransferAbortPacket abort = new TransferAbortPacket(); abort.TransferInfo.ChannelType = (int)download.Channel; abort.TransferInfo.TransferID = download.ID; Client.Network.SendPacket(abort, download.Simulator); download.Success = false; lock (Transfers) Transfers.Remove(download.ID); // Fire the event with our transfer that contains Success = false if (OnAssetReceived != null) { try { OnAssetReceived(download, null); } catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); } } return; } } // This assumes that every transfer packet except the last one is exactly 1000 bytes, // hopefully that is a safe assumption to make Buffer.BlockCopy(asset.TransferData.Data, 0, download.AssetData, 1000 * asset.TransferData.Packet, asset.TransferData.Data.Length); download.Transferred += asset.TransferData.Data.Length; //Client.DebugLog(String.Format("Transfer packet {0}, received {1}/{2}/{3} bytes for asset {4}", // asset.TransferData.Packet, asset.TransferData.Data.Length, transfer.Transferred, transfer.Size, // transfer.AssetID.ToString())); // Check if we downloaded the full asset if (download.Transferred >= download.Size) { Client.DebugLog("Transfer for asset " + download.AssetID.ToString() + " completed"); download.Success = true; lock (Transfers) Transfers.Remove(download.ID); if (OnAssetReceived != null) { try { OnAssetReceived(download, WrapAsset(download)); } catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); } } } } }