mirror of
https://github.com/NotAKidoS/NAK_CVR_Mods.git
synced 2025-09-02 22:39:22 +00:00
144 lines
No EOL
4.6 KiB
C#
144 lines
No EOL
4.6 KiB
C#
using System.Diagnostics;
|
|
using System.Net.Http.Headers;
|
|
using ABI_RC.Core.IO;
|
|
|
|
namespace NAK.BetterContentLoading;
|
|
|
|
public partial class DownloadManager2
|
|
{
|
|
private async Task ProcessDownload(DownloadTask2 task2)
|
|
{
|
|
using var client = new HttpClient();
|
|
|
|
// Set up resume headers if we have a resume token
|
|
if (!string.IsNullOrEmpty(task2.ResumeToken))
|
|
{
|
|
client.DefaultRequestHeaders.Range = new RangeHeaderValue(task2.BytesRead, null);
|
|
}
|
|
|
|
using var response = await client.GetAsync(task2.Info.AssetUrl, HttpCompletionOption.ResponseHeadersRead);
|
|
using var dataStream = await response.Content.ReadAsStreamAsync();
|
|
|
|
// Open file in append mode if resuming, otherwise create new
|
|
using var fileStream = new FileStream(
|
|
task2.TargetPath,
|
|
string.IsNullOrEmpty(task2.ResumeToken) ? FileMode.Create : FileMode.Append,
|
|
FileAccess.Write);
|
|
|
|
bool isEligibleForThrottle = task2.Info.FileSize > THROTTLE_THRESHOLD;
|
|
var stopwatch = new Stopwatch();
|
|
|
|
int bytesRead;
|
|
do
|
|
{
|
|
if (task2.Status == DownloadTaskStatus.Paused)
|
|
{
|
|
task2.ResumeToken = GenerateResumeToken(task2);
|
|
await fileStream.FlushAsync();
|
|
return;
|
|
}
|
|
|
|
if (task2.Status != DownloadTaskStatus.Downloading)
|
|
{
|
|
HandleCancellation(task2, dataStream, fileStream);
|
|
return;
|
|
}
|
|
|
|
stopwatch.Restart();
|
|
var lengthToRead = isEligibleForThrottle ?
|
|
ComputeUsableBandwidthPerDownload() :
|
|
16384;
|
|
|
|
var buffer = new byte[lengthToRead];
|
|
bytesRead = await dataStream.ReadAsync(buffer, 0, lengthToRead);
|
|
|
|
if (isEligibleForThrottle)
|
|
Interlocked.Add(ref _bytesReadLastSecond, bytesRead);
|
|
|
|
await fileStream.WriteAsync(buffer, 0, bytesRead);
|
|
UpdateProgress(task2, bytesRead);
|
|
|
|
} while (bytesRead > 0);
|
|
|
|
CompleteDownload(task2);
|
|
}
|
|
|
|
private string GenerateResumeToken(DownloadTask2 task2)
|
|
{
|
|
// Generate a unique token that includes file position and hash
|
|
return $"{task2.BytesRead}:{DateTime.UtcNow.Ticks}";
|
|
}
|
|
|
|
private async Task FinalizeDownload(DownloadTask2 task2)
|
|
{
|
|
var tempPath = task2.CachePath + ".tmp";
|
|
|
|
try
|
|
{
|
|
// Decrypt the file if needed
|
|
if (task2.Info.EncryptionAlgorithm != 0)
|
|
{
|
|
await DecryptFile(tempPath, task2.CachePath, task2.Info);
|
|
File.Delete(tempPath);
|
|
}
|
|
else
|
|
{
|
|
File.Move(tempPath, task2.CachePath);
|
|
}
|
|
|
|
CompleteDownload(task2);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// _logger.Error($"Failed to finalize download for {task.Info.AssetId}: {ex.Message}");
|
|
task2.Status = DownloadTaskStatus.Failed;
|
|
File.Delete(tempPath);
|
|
_activeDownloads.TryRemove(task2.Info.DownloadId, out _);
|
|
}
|
|
}
|
|
|
|
private async Task DecryptFile(string sourcePath, string targetPath, DownloadInfo info)
|
|
{
|
|
// Implementation of file decryption based on EncryptionAlgorithm
|
|
// This would use the FileKey from the DownloadInfo
|
|
throw new NotImplementedException("File decryption not implemented");
|
|
}
|
|
|
|
private void HandleCancellation(DownloadTask2 task2, Stream dataStream, Stream fileStream)
|
|
{
|
|
if (task2.Status != DownloadTaskStatus.Failed)
|
|
task2.Status = DownloadTaskStatus.Cancelled;
|
|
|
|
dataStream.Close();
|
|
fileStream.Close();
|
|
|
|
task2.Progress = 0;
|
|
task2.BytesRead = 0;
|
|
|
|
_activeDownloads.TryRemove(task2.Info.DownloadId, out _);
|
|
}
|
|
|
|
private void UpdateProgress(DownloadTask2 task2, int bytesRead)
|
|
{
|
|
task2.BytesRead += bytesRead;
|
|
task2.Progress = Math.Clamp(
|
|
(int)(((float)task2.BytesRead / task2.Info.FileSize) * 100f),
|
|
0, 100);
|
|
}
|
|
|
|
private void CompleteDownload(DownloadTask2 task2)
|
|
{
|
|
task2.Status = DownloadTaskStatus.Complete;
|
|
task2.Progress = 100;
|
|
_activeDownloads.TryRemove(task2.Info.DownloadId, out _);
|
|
_completedDownloads.TryAdd(task2.Info.DownloadId, task2);
|
|
|
|
lock (_downloadLock)
|
|
{
|
|
if (_queuedDownloads.TryDequeue(out var nextTask, out _))
|
|
{
|
|
StartDownload(nextTask);
|
|
}
|
|
}
|
|
}
|
|
} |