Bug fixes and revised DownloadManager for client
This commit is contained in:
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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}]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
Reference in New Issue
Block a user