Bug fixes and revised DownloadManager for client

This commit is contained in:
EntenKoeniq
2022-04-06 05:10:29 +02:00
parent 2fd3ef32fb
commit a6d2acac79
3 changed files with 146 additions and 46 deletions

View File

@ -1,66 +1,156 @@
using System.IO; using System.IO;
using System.Linq;
using System.Collections.Generic;
namespace CoopClient namespace CoopClient
{ {
internal class DownloadManager internal static class DownloadManager
{ {
public byte FileID { get; set; } private static readonly List<DownloadFile> _downloadFiles = new List<DownloadFile>();
public Packets.DataFileType FileType { get; set; } private static readonly Dictionary<byte, FileStream> _streams = new Dictionary<byte, FileStream>();
private string FileName = string.Empty; private static readonly List<byte> _filesFinished = new List<byte>();
public long FileLength { get; set; }
private readonly FileStream _stream; public static void AddFile(byte id, Packets.DataFileType type, string name, long length)
public DownloadManager(string fileName)
{ {
FileName = fileName;
string downloadFolder = $"scripts\\resources\\{Main.MainSettings.LastServerAddress.Replace(":", ".")}"; string downloadFolder = $"scripts\\resources\\{Main.MainSettings.LastServerAddress.Replace(":", ".")}";
if (!Directory.Exists(downloadFolder)) if (!Directory.Exists(downloadFolder))
{ {
Directory.CreateDirectory(downloadFolder); Directory.CreateDirectory(downloadFolder);
if (FileAlreadyExists(downloadFolder))
{
// Send the server we are already done
Main.MainNetworking.SendDownloadFinish(FileID);
return;
}
} }
_stream = new FileStream($"{downloadFolder}\\{fileName}", File.Exists($"{downloadFolder}\\{fileName}") ? FileMode.Truncate : FileMode.CreateNew); if (FileAlreadyExists(downloadFolder, name, length))
{
// Send the server we are already done
Main.MainNetworking.SendDownloadFinish(id);
lock (_filesFinished)
{
_filesFinished.Add(id);
}
return;
}
lock (_downloadFiles)
{
_downloadFiles.Add(new DownloadFile()
{
FileID = id,
FileType = type,
FileName = name,
FileLength = length
});
}
lock (_streams)
{
_streams.Add(id, new FileStream($"{downloadFolder}\\{name}", FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite));
}
} }
/// <summary> /// <summary>
/// Check if the file already exists and if the size correct otherwise delete this file /// Check if the file already exists and if the size correct otherwise delete this file
/// </summary> /// </summary>
/// <param name="folder"></param> /// <param name="folder"></param>
private bool FileAlreadyExists(string folder) /// <param name="name"></param>
/// <param name="length"></param>
/// <returns></returns>
private static bool FileAlreadyExists(string folder, string name, long length)
{ {
string filePath = $"{folder}\\{FileName}"; string filePath = $"{folder}\\{name}";
if (File.Exists(filePath)) if (File.Exists(filePath))
{ {
if (new FileInfo(filePath).Length == FileLength) if (new FileInfo(filePath).Length == length)
{ {
return true; return true;
} }
else
{ // Delete the file because the length is wrong (maybe the file was updated)
// Delete the file because the length is wrong (maybe the file was updated) File.Delete(filePath);
File.Delete(filePath);
}
} }
return false; return false;
} }
public void DownloadPart(byte[] data) public static void Write(byte id, byte[] data)
{ {
_stream.Write(data, 0, data.Length); lock (_filesFinished)
if (data.Length >= FileLength)
{ {
_stream.Close(); if (_filesFinished.Contains(id))
_stream.Dispose(); {
Cancel(id);
return;
}
}
lock (_streams)
{
FileStream fs = _streams.ContainsKey(id) ? _streams[id] : null;
if (fs == null)
{
throw new System.Exception($"Stream for file {id} doesn't found!");
}
fs.Write(data, 0, data.Length);
lock (_downloadFiles)
{
DownloadFile file = _downloadFiles.FirstOrDefault(x => x.FileID == id);
if (file == null)
{
throw new System.Exception($"File {id} couldn't ne found in list!");
}
if (data.Length >= file.FileLength)
{
Cancel(id);
}
}
}
}
public static void Cancel(byte id)
{
lock (_streams) lock (_downloadFiles)
{
FileStream fs = _streams.ContainsKey(id) ? _streams[id] : null;
if (fs != null)
{
fs.Close();
fs.Dispose();
_streams.Remove(id);
}
if (_downloadFiles.Any(x => x.FileID == id))
{
_downloadFiles.Remove(_downloadFiles.First(x => x.FileID == id));
}
}
}
public static void Cleanup()
{
lock (_streams) lock (_downloadFiles) lock (_filesFinished)
{
foreach (var stream in _streams)
{
stream.Value.Close();
stream.Value.Dispose();
}
_streams.Clear();
_downloadFiles.Clear();
_filesFinished.Clear();
} }
} }
} }
internal class DownloadFile
{
public byte FileID { get; set; } = 0;
public Packets.DataFileType FileType { get; set; } = Packets.DataFileType.Script;
public string FileName { get; set; } = string.Empty;
public long FileLength { get; set; } = 0;
}
} }

View File

@ -22,8 +22,6 @@ namespace CoopClient
public int BytesReceived = 0; public int BytesReceived = 0;
public int BytesSend = 0; public int BytesSend = 0;
private readonly Dictionary<byte, DownloadManager> _downloads = new Dictionary<byte, DownloadManager>();
public void DisConnectFromServer(string address) public void DisConnectFromServer(string address)
{ {
if (IsOnServer()) if (IsOnServer())
@ -136,10 +134,11 @@ namespace CoopClient
} }
break; break;
case NetConnectionStatus.Disconnected: case NetConnectionStatus.Disconnected:
DownloadManager.Cleanup();
// Reset all values // Reset all values
Latency = 0; Latency = 0;
LastPlayerFullSync = 0; LastPlayerFullSync = 0;
_downloads.Clear();
Main.CleanUpWorld(); Main.CleanUpWorld();
@ -463,12 +462,7 @@ namespace CoopClient
Packets.FileTransferRequest packet = new Packets.FileTransferRequest(); Packets.FileTransferRequest packet = new Packets.FileTransferRequest();
packet.NetIncomingMessageToPacket(data); packet.NetIncomingMessageToPacket(data);
_downloads.Add(packet.ID, new DownloadManager(packet.FileName) DownloadManager.AddFile(packet.ID, (Packets.DataFileType)packet.FileType, packet.FileName, packet.FileLength);
{
FileID = packet.ID,
FileType = (Packets.DataFileType)packet.FileType,
FileLength = packet.FileLength
});
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -487,18 +481,14 @@ namespace CoopClient
Packets.FileTransferTick packet = new Packets.FileTransferTick(); Packets.FileTransferTick packet = new Packets.FileTransferTick();
packet.NetIncomingMessageToPacket(data); packet.NetIncomingMessageToPacket(data);
KeyValuePair<byte, DownloadManager> dm = _downloads.FirstOrDefault(x => x.Key == packet.ID); DownloadManager.Write(packet.ID, packet.FileChunk);
if (dm.Value == null)
{
throw new Exception("File to download not found!");
}
dm.Value.DownloadPart(packet.FileChunk);
} }
catch (Exception ex) catch (Exception ex)
{ {
GTA.UI.Notification.Show("~r~~h~Packet Error"); GTA.UI.Notification.Show("~r~~h~Packet Error");
Logger.Write($"[{packetType}] {ex.Message}", Logger.LogLevel.Server); Logger.Write($"[{packetType}] {ex.Message}", Logger.LogLevel.Server);
Logger.Write($"[{packetType}] {ex.Source}", Logger.LogLevel.Server);
Logger.Write($"[{packetType}] {ex.StackTrace}", Logger.LogLevel.Server);
Client.Disconnect($"Packet Error [{packetType}]"); Client.Disconnect($"Packet Error [{packetType}]");
} }
} }

View File

@ -107,6 +107,8 @@ namespace CoopServer
} }
} }
}); });
Logging.Debug($"Clients [{_clients.Count}]");
} }
public static void RemoveClient(long nethandle) public static void RemoveClient(long nethandle)
@ -178,6 +180,24 @@ namespace CoopServer
}); });
} }
~DownloadClient()
{
NetConnection conn = Server.MainNetServer.Connections.FirstOrDefault(x => x.RemoteUniqueIdentifier == NetHandle);
if (conn == null)
{
return;
}
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
new Packets.FileTransferComplete()
{
ID = 0x0
}.PacketToNetOutGoingMessage(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, conn, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.File);
}
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>