RAGECOOP-V/Server/DownloadManager.cs

214 lines
6.4 KiB
C#
Raw Normal View History

2022-04-03 18:46:57 +02:00
using System.IO;
using System.Linq;
using System.Collections.Generic;
2022-04-03 02:27:30 +02:00
using Lidgren.Network;
namespace CoopServer
{
2022-04-02 23:02:49 +02:00
internal static class DownloadManager
{
2022-04-02 23:02:49 +02:00
private static readonly List<DownloadClient> _clients = new();
private static readonly List<DownloadFile> _files = new();
public static bool AnyFileExists = false;
2022-04-02 23:02:49 +02:00
public static void InsertClient(long nethandle)
{
2022-04-02 23:02:49 +02:00
if (!AnyFileExists)
{
return;
}
2022-04-03 18:46:57 +02:00
_clients.Add(new DownloadClient(nethandle, new(_files)));
2022-04-02 23:02:49 +02:00
}
public static bool CheckForDirectoryAndFiles()
{
2022-04-03 02:27:30 +02:00
string[] filePaths;
if (!Directory.Exists("clientside"))
{
return false;
}
2022-04-03 02:27:30 +02:00
filePaths = Directory.GetFiles("clientside");
if (filePaths.Length == 0)
2022-04-02 23:02:49 +02:00
{
return false;
}
2022-04-03 02:27:30 +02:00
byte fileCount = 0;
2022-04-02 23:02:49 +02:00
foreach (string file in filePaths)
{
FileInfo fileInfo = new(file);
// ONLY JAVASCRIPT AND JSON FILES!
if (!new string[] { ".js", ".json" }.Any(x => x == fileInfo.Extension))
{
2022-04-02 23:02:49 +02:00
Logging.Warning("Only files with \"*.js\" and \"*.json\" can be sent!");
continue;
}
2022-04-03 02:27:30 +02:00
int MAX_BUFFER = fileInfo.Length < 5120 ? (int)fileInfo.Length : 5120; // 5KB
byte[] buffer = new byte[MAX_BUFFER];
bool fileCreated = false;
DownloadFile newFile = null;
using (FileStream fs = File.Open(file, FileMode.Open, FileAccess.Read))
using (BufferedStream bs = new(fs))
{
2022-04-03 02:27:30 +02:00
while (bs.Read(buffer, 0, MAX_BUFFER) != 0) // Reading 5KB chunks at time
{
2022-04-03 18:46:57 +02:00
if (!fileCreated && (fileCreated = true))
{
2022-04-03 18:46:57 +02:00
newFile = new() { FileID = fileCount, FileName = fileInfo.Name, FileLength = fileInfo.Length, FileData = new() };
}
2022-04-03 03:22:28 +02:00
newFile.FileData.Add(buffer);
}
}
2022-04-02 23:02:49 +02:00
_files.Add(newFile);
2022-04-03 02:27:30 +02:00
fileCount++;
}
2022-04-02 23:02:49 +02:00
AnyFileExists = true;
return true;
}
public static void Tick()
{
_clients.ForEach(client =>
{
2022-04-03 02:27:30 +02:00
if (!client.SendFiles())
2022-04-02 23:02:49 +02:00
{
Client x = Server.Clients.FirstOrDefault(x => x.NetHandle == client.NetHandle);
if (x != null)
{
2022-04-03 02:27:30 +02:00
x.FilesReceived = true;
2022-04-02 23:02:49 +02:00
}
}
});
}
2022-04-02 23:02:49 +02:00
public static void RemoveClient(long nethandle)
{
2022-04-02 23:02:49 +02:00
DownloadClient client = _clients.FirstOrDefault(x => x.NetHandle == nethandle);
if (client != null)
{
_clients.Remove(client);
}
}
2022-04-03 02:27:30 +02:00
/// <summary>
/// We try to remove the client when all files have been sent
/// </summary>
/// <param name="nethandle"></param>
/// <param name="id"></param>
public static void TryToRemoveClient(long nethandle, int id)
{
DownloadClient client = _clients.FirstOrDefault(x => x.NetHandle == nethandle);
if (client == null)
{
return;
}
client.FilePosition++;
if (client.DownloadComplete())
{
_clients.Remove(client);
}
}
2022-04-02 23:02:49 +02:00
}
internal class DownloadClient
{
2022-04-03 02:27:30 +02:00
public long NetHandle = 0;
2022-04-03 18:46:57 +02:00
private readonly List<DownloadFile> _files = null;
2022-04-03 02:27:30 +02:00
public int FilePosition = 0;
2022-04-03 18:46:57 +02:00
private int _fileDataPosition = 0;
2022-04-03 02:27:30 +02:00
public DownloadClient(long nethandle, List<DownloadFile> files)
{
NetHandle = nethandle;
2022-04-03 18:46:57 +02:00
_files = files;
2022-04-03 02:27:30 +02:00
NetConnection conn = Server.MainNetServer.Connections.FirstOrDefault(x => x.RemoteUniqueIdentifier == NetHandle);
if (conn != null)
{
2022-04-03 18:46:57 +02:00
_files.ForEach(file =>
2022-04-03 02:27:30 +02:00
{
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
new Packets.FileRequest()
{
ID = file.FileID,
FileType = (byte)Packets.DataFileType.Script,
FileName = file.FileName,
FileLength = file.FileLength
}.PacketToNetOutGoingMessage(outgoingMessage);
Server.MainNetServer.SendMessage(outgoingMessage, conn, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.File);
});
}
}
2022-04-02 23:02:49 +02:00
/// <summary>
///
/// </summary>
/// <returns>true if files should be sent otherwise false</returns>
2022-04-03 02:27:30 +02:00
public bool SendFiles()
2022-04-02 23:02:49 +02:00
{
2022-04-03 02:27:30 +02:00
if (DownloadComplete())
{
return false;
}
2022-04-03 18:46:57 +02:00
DownloadFile file = _files[FilePosition];
2022-04-02 23:02:49 +02:00
2022-04-03 18:46:57 +02:00
Send(NetHandle, file);
2022-04-02 23:02:49 +02:00
2022-04-03 18:46:57 +02:00
if (_fileDataPosition >= file.FileData.Count)
2022-04-02 23:02:49 +02:00
{
2022-04-03 02:27:30 +02:00
FilePosition++;
2022-04-03 18:46:57 +02:00
_fileDataPosition = 0;
2022-04-02 23:02:49 +02:00
2022-04-03 02:27:30 +02:00
return DownloadComplete();
2022-04-02 23:02:49 +02:00
}
return true;
}
2022-04-03 02:27:30 +02:00
2022-04-03 18:46:57 +02:00
private void Send(long nethandle, DownloadFile file)
{
2022-04-03 02:27:30 +02:00
NetConnection conn = Server.MainNetServer.Connections.FirstOrDefault(x => x.RemoteUniqueIdentifier == nethandle);
if (conn == null)
{
return;
}
NetOutgoingMessage outgoingMessage = Server.MainNetServer.CreateMessage();
2022-04-03 18:46:57 +02:00
new Packets.FileTransferTick() { ID = file.FileID, FileChunk = file.FileData[_fileDataPosition++] }.PacketToNetOutGoingMessage(outgoingMessage);
2022-04-03 02:27:30 +02:00
Server.MainNetServer.SendMessage(outgoingMessage, conn, NetDeliveryMethod.ReliableOrdered, (byte)ConnectionChannel.File);
}
2022-04-03 18:46:57 +02:00
public bool DownloadComplete()
{
2022-04-03 18:46:57 +02:00
return FilePosition >= _files.Count;
}
}
2022-04-03 18:46:57 +02:00
internal class DownloadFile
{
public byte FileID { get; set; } = 0;
public string FileName { get; set; } = string.Empty;
public long FileLength { get; set; } = 0;
public List<byte[]> FileData { get; set; } = null;
}
}