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