Files
RAGECOOP-V/Client/Scripts/Networking/DownloadManager.cs

180 lines
6.1 KiB
C#
Raw Normal View History

2022-10-23 19:02:39 +08:00
using System;
2022-07-20 17:50:01 +08:00
using System.Collections.Generic;
using System.IO;
using System.Linq;
2022-11-16 17:37:31 +08:00
using RageCoop.Client.Scripting;
2022-10-23 19:02:39 +08:00
using RageCoop.Core;
2022-11-16 17:37:31 +08:00
using static RageCoop.Client.Shared;
2022-04-02 16:40:24 +02:00
2022-05-22 15:55:26 +08:00
namespace RageCoop.Client
2022-04-02 16:40:24 +02:00
{
internal static class DownloadManager
2022-04-02 16:40:24 +02:00
{
2022-10-23 19:02:39 +08:00
private static readonly Dictionary<int, DownloadFile> InProgressDownloads = new Dictionary<int, DownloadFile>();
private static readonly HashSet<string> _resources = new HashSet<string>();
2022-07-01 12:22:31 +08:00
static DownloadManager()
{
2022-10-23 19:02:39 +08:00
Networking.RequestHandlers.Add(PacketType.FileTransferRequest, data =>
2022-07-01 12:22:31 +08:00
{
var fr = new Packets.FileTransferRequest();
2022-08-06 10:43:24 +08:00
fr.Deserialize(data);
2022-10-23 19:02:39 +08:00
if (fr.Name.EndsWith(".res")) _resources.Add(fr.Name);
return new Packets.FileTransferResponse
2022-07-01 12:22:31 +08:00
{
2022-09-06 21:46:35 +08:00
ID = fr.ID,
2022-10-23 19:02:39 +08:00
Response = AddFile(fr.ID, fr.Name, fr.FileLength)
? FileResponse.NeedToDownload
: FileResponse.AlreadyExists
2022-07-01 12:22:31 +08:00
};
});
2022-10-23 19:02:39 +08:00
Networking.RequestHandlers.Add(PacketType.FileTransferComplete, data =>
2022-07-01 12:22:31 +08:00
{
2022-10-23 19:02:39 +08:00
var packet = new Packets.FileTransferComplete();
2022-08-06 10:43:24 +08:00
packet.Deserialize(data);
2022-07-01 12:22:31 +08:00
2023-02-13 17:51:18 +08:00
Log.Debug($"Finalizing download:{packet.ID}");
2022-07-01 12:22:31 +08:00
Complete(packet.ID);
// Inform the server that the download is completed
2022-10-23 19:02:39 +08:00
return new Packets.FileTransferResponse
2022-07-01 12:22:31 +08:00
{
2022-09-06 21:46:35 +08:00
ID = packet.ID,
Response = FileResponse.Completed
2022-07-01 12:22:31 +08:00
};
});
2022-10-23 19:02:39 +08:00
Networking.RequestHandlers.Add(PacketType.AllResourcesSent, data =>
2022-07-01 12:22:31 +08:00
{
try
{
2022-11-16 17:37:31 +08:00
Directory.CreateDirectory(ResourceFolder);
2023-02-13 17:51:18 +08:00
MainRes.Load(ResourceFolder, _resources.ToArray());
2022-10-23 19:02:39 +08:00
return new Packets.FileTransferResponse { ID = 0, Response = FileResponse.Loaded };
2022-07-01 12:22:31 +08:00
}
2022-07-20 17:50:01 +08:00
catch (Exception ex)
2022-07-01 12:22:31 +08:00
{
2023-02-13 17:51:18 +08:00
Log.Error("Error occurred when loading server resource");
Log.Error(ex);
2022-10-23 19:02:39 +08:00
return new Packets.FileTransferResponse { ID = 0, Response = FileResponse.LoadFailed };
2022-07-01 12:22:31 +08:00
}
});
}
2022-10-23 19:02:39 +08:00
2022-11-16 17:37:31 +08:00
public static string ResourceFolder => Path.GetFullPath(Path.Combine(DataPath, "Resources",
API.ServerEndPoint.ToString().Replace(":", ".")));
2022-10-23 19:02:39 +08:00
public static event EventHandler<string> DownloadCompleted;
2022-07-01 12:22:31 +08:00
public static bool AddFile(int id, string name, long length)
2022-04-02 16:40:24 +02:00
{
2022-07-19 17:15:53 +08:00
var path = $"{ResourceFolder}\\{name}";
2023-02-13 17:51:18 +08:00
Log.Debug($"Downloading file to {path} , id:{id}");
2022-07-19 17:15:53 +08:00
if (!Directory.Exists(Directory.GetParent(path).FullName))
Directory.CreateDirectory(Directory.GetParent(path).FullName);
2022-07-02 17:14:56 +08:00
if (FileAlreadyExists(ResourceFolder, name, length))
{
2023-02-13 17:51:18 +08:00
Log.Debug($"File already exists! canceling download:{name}");
2022-07-19 17:15:53 +08:00
DownloadCompleted?.Invoke(null, Path.Combine(ResourceFolder, name));
2022-07-01 12:22:31 +08:00
return false;
}
2022-10-23 19:02:39 +08:00
2022-07-19 17:15:53 +08:00
/*
if (!name.EndsWith(".zip"))
{
2023-02-13 17:51:18 +08:00
Log.Error($"File download blocked! [{name}]");
2022-07-01 12:22:31 +08:00
return false;
}
2022-07-19 17:15:53 +08:00
*/
lock (InProgressDownloads)
{
2022-10-23 19:02:39 +08:00
InProgressDownloads.Add(id, new DownloadFile
{
FileID = id,
FileName = name,
FileLength = length,
2022-07-19 17:15:53 +08:00
Stream = new FileStream(path, FileMode.CreateNew, FileAccess.Write, FileShare.ReadWrite)
});
2022-04-02 18:11:30 +02:00
}
2022-10-23 19:02:39 +08:00
2022-07-01 12:22:31 +08:00
return true;
2022-04-02 16:40:24 +02:00
}
2022-04-02 18:11:30 +02:00
/// <summary>
2022-10-23 19:02:39 +08:00
/// Check if the file already exists and if the size correct otherwise delete this file
2022-04-02 18:11:30 +02:00
/// </summary>
/// <param name="folder"></param>
/// <param name="name"></param>
/// <param name="length"></param>
/// <returns></returns>
private static bool FileAlreadyExists(string folder, string name, long length)
2022-04-02 16:40:24 +02:00
{
2022-10-23 19:02:39 +08:00
var filePath = $"{folder}\\{name}";
2022-04-02 18:11:30 +02:00
if (File.Exists(filePath))
{
2022-10-23 19:02:39 +08:00
if (new FileInfo(filePath).Length == length) return true;
// Delete the file because the length is wrong (maybe the file was updated)
File.Delete(filePath);
}
return false;
}
public static void Write(int id, byte[] chunk)
{
lock (InProgressDownloads)
{
2022-10-23 19:02:39 +08:00
if (InProgressDownloads.TryGetValue(id, out var file))
file.Stream.Write(chunk, 0, chunk.Length);
else
2023-02-13 17:51:18 +08:00
Log.Trace($"Received unhandled file chunk:{id}");
}
}
public static void Complete(int id)
{
2022-10-23 19:02:39 +08:00
if (InProgressDownloads.TryGetValue(id, out var f))
{
2022-07-01 12:22:31 +08:00
InProgressDownloads.Remove(id);
f.Dispose();
2023-02-13 17:51:18 +08:00
Log.Info($"Download finished:{f.FileName}");
2022-07-19 17:15:53 +08:00
DownloadCompleted?.Invoke(null, Path.Combine(ResourceFolder, f.FileName));
}
else
{
2023-02-13 17:51:18 +08:00
Log.Error($"Download not found! {id}");
}
2022-04-02 18:11:30 +02:00
}
public static void Cleanup()
2022-04-02 18:11:30 +02:00
{
lock (InProgressDownloads)
2022-04-02 18:11:30 +02:00
{
2022-10-23 19:02:39 +08:00
foreach (var file in InProgressDownloads.Values) file.Dispose();
InProgressDownloads.Clear();
2022-04-02 18:11:30 +02:00
}
2022-10-23 19:02:39 +08:00
_resources.Clear();
2022-04-02 16:40:24 +02:00
}
}
2022-07-20 17:50:01 +08:00
internal class DownloadFile : IDisposable
{
2022-10-23 19:02:39 +08:00
public int FileID { get; set; }
public string FileName { get; set; } = string.Empty;
2022-10-23 19:02:39 +08:00
public long FileLength { get; set; }
2022-04-06 06:52:02 +02:00
public long FileWritten { get; set; } = 0;
public FileStream Stream { get; set; }
2022-10-23 19:02:39 +08:00
public void Dispose()
{
2022-09-06 21:46:35 +08:00
if (Stream != null)
{
Stream.Flush();
Stream.Close();
Stream.Dispose();
}
}
}
2022-10-23 19:02:39 +08:00
}