mirror of
https://github.com/Stone-Red-Code/HyperbolicDownloader.git
synced 2026-09-04 00:56:09 +02:00
- Optimize downloading process
- Add expiration time to inactive hosts
This commit is contained in:
@@ -8,6 +8,13 @@ internal class FilesManager
|
||||
|
||||
public bool TryAdd(string filePath, out HyperFileInfo? fileInfo, out string? errorMessage)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(filePath))
|
||||
{
|
||||
fileInfo = null;
|
||||
errorMessage = "Path is empty!";
|
||||
return false;
|
||||
}
|
||||
|
||||
string fullPath = Path.GetFullPath(filePath);
|
||||
|
||||
if (!File.Exists(fullPath))
|
||||
|
||||
@@ -40,9 +40,10 @@ internal class HostsManager
|
||||
SaveHosts();
|
||||
}
|
||||
|
||||
public void RemoveInactiveHosts()
|
||||
public int CheckHostsActivity()
|
||||
{
|
||||
List<NetworkSocket> hostsToRemove = new List<NetworkSocket>();
|
||||
int activeHostsCount = 0;
|
||||
foreach (NetworkSocket host in hosts)
|
||||
{
|
||||
ConsoleExt.Write($"{host.IPAddress}:{host.Port} > ???", ConsoleColor.DarkYellow);
|
||||
@@ -55,16 +56,24 @@ internal class HostsManager
|
||||
if (tcpClient.Connected)
|
||||
{
|
||||
ConsoleExt.WriteLine($"{host.IPAddress}:{host.Port} > Active", ConsoleColor.Green);
|
||||
host.LastActive = DateTime.Now;
|
||||
activeHostsCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
hostsToRemove.Add(host);
|
||||
if (DateTime.Now - host.LastActive >= new TimeSpan(24, 0, 0))
|
||||
{
|
||||
hostsToRemove.Add(host);
|
||||
}
|
||||
ConsoleExt.WriteLine($"{host.IPAddress}:{host.Port} > Inactive", ConsoleColor.Red);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
hostsToRemove.Add(host);
|
||||
if (DateTime.Now - host.LastActive >= new TimeSpan(24, 0, 0))
|
||||
{
|
||||
hostsToRemove.Add(host);
|
||||
}
|
||||
Console.CursorLeft = 0;
|
||||
ConsoleExt.WriteLine($"{host.IPAddress}:{host.Port} > Inactive", ConsoleColor.Red);
|
||||
}
|
||||
@@ -76,6 +85,7 @@ internal class HostsManager
|
||||
}
|
||||
|
||||
SaveHosts();
|
||||
return activeHostsCount;
|
||||
}
|
||||
|
||||
public List<NetworkSocket> ToList()
|
||||
@@ -83,7 +93,7 @@ internal class HostsManager
|
||||
return hosts.ToList();
|
||||
}
|
||||
|
||||
private void SaveHosts()
|
||||
public void SaveHosts()
|
||||
{
|
||||
File.WriteAllText(Program.HostsFilePath, JsonSerializer.Serialize(hosts));
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace HyperbolicDownloader.Networking
|
||||
public bool IsListening { get; private set; } = false;
|
||||
|
||||
private TcpListener? tcpListener;
|
||||
private FilesManager filesManager;
|
||||
private readonly FilesManager filesManager;
|
||||
private readonly Dictionary<string, (Type type, Delegate method)> events = new();
|
||||
|
||||
public NetworkClient(FilesManager filesManager)
|
||||
@@ -107,7 +107,7 @@ namespace HyperbolicDownloader.Networking
|
||||
NetworkStream nwStream = client.GetStream();
|
||||
byte[] buffer = new byte[client.ReceiveBufferSize];
|
||||
|
||||
int bytesRead = await nwStream.ReadAsync(buffer, 0, client.ReceiveBufferSize);
|
||||
int bytesRead = await nwStream.ReadAsync(buffer.AsMemory(0, client.ReceiveBufferSize));
|
||||
|
||||
string dataReceived = Encoding.ASCII.GetString(buffer, 0, bytesRead);
|
||||
|
||||
|
||||
@@ -4,10 +4,12 @@ internal class NetworkSocket
|
||||
{
|
||||
public string IPAddress { get; set; }
|
||||
public int Port { get; set; }
|
||||
public DateTime LastActive { get; set; }
|
||||
|
||||
public NetworkSocket(string ipAddress, int port)
|
||||
public NetworkSocket(string ipAddress, int port, DateTime lastActive)
|
||||
{
|
||||
IPAddress = ipAddress;
|
||||
Port = port;
|
||||
LastActive = lastActive;
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,21 @@ internal class Program
|
||||
public const string HostsFilePath = "Hosts.json";
|
||||
public const string FilesInfoPath = "Files.json";
|
||||
|
||||
private static int publicPort;
|
||||
private static readonly int privatePort = 3055;
|
||||
public static int PublicPort { get; private set; }
|
||||
public static int PrivatePort { get; } = 3055;
|
||||
|
||||
public static IPAddress? PublicIpAddress
|
||||
{
|
||||
get
|
||||
{
|
||||
if (device is not null)
|
||||
{
|
||||
return device.GetExternalIPAsync().GetAwaiter().GetResult();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static NatDevice? device;
|
||||
private static Mapping? portMapping;
|
||||
private static readonly HostsManager hostsManager = new();
|
||||
@@ -50,7 +63,7 @@ internal class Program
|
||||
_ = await OpenPorts();
|
||||
|
||||
ConsoleExt.WriteLine($"The private IP Address is: {NetworkUtilities.GetIP4Adress()} ", ConsoleColor.Green);
|
||||
ConsoleExt.WriteLine($"The private port is: {privatePort}", ConsoleColor.Green);
|
||||
ConsoleExt.WriteLine($"The private port is: {PrivatePort}", ConsoleColor.Green);
|
||||
|
||||
Console.WriteLine("Starting TCP listener...");
|
||||
|
||||
@@ -60,7 +73,7 @@ internal class Program
|
||||
networkClient.ListenTo<List<NetworkSocket>>("DiscoverAnswer", DiscoverAnswer);
|
||||
networkClient.ListenTo<string>("Message", ReciveMessage);
|
||||
networkClient.ListenTo<string>("HasFile", HasFile);
|
||||
networkClient.StartListening(privatePort);
|
||||
networkClient.StartListening(PrivatePort);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
@@ -71,23 +84,25 @@ internal class Program
|
||||
BroadcastClient broadcastClient = new BroadcastClient();
|
||||
|
||||
Console.WriteLine("Running local discovery routine...");
|
||||
BroadcastClient.Send(BroadcastPort, privatePort.ToString());
|
||||
BroadcastClient.Send(BroadcastPort, PrivatePort.ToString());
|
||||
await Task.Delay(5000);
|
||||
|
||||
int activeHostsCount = 0;
|
||||
if (hostsManager.Count > 0)
|
||||
{
|
||||
Console.WriteLine("Checking if hosts are active...");
|
||||
hostsManager.RemoveInactiveHosts();
|
||||
activeHostsCount = hostsManager.CheckHostsActivity();
|
||||
}
|
||||
|
||||
if (hostsManager.Count == 0)
|
||||
if (activeHostsCount == 0)
|
||||
{
|
||||
hostsManager.AddRange(await Setup.ConfigureHost());
|
||||
Console.WriteLine("Checking if hosts are active...");
|
||||
hostsManager.RemoveInactiveHosts();
|
||||
activeHostsCount = hostsManager.CheckHostsActivity();
|
||||
}
|
||||
|
||||
Console.WriteLine($"{hostsManager.Count} active host(s).");
|
||||
Console.WriteLine($"{hostsManager.Count} known host(s).");
|
||||
Console.WriteLine($"{activeHostsCount} active host(s).");
|
||||
Console.WriteLine("Starting broadcast listener...");
|
||||
broadcastClient.StartListening(BroadcastPort);
|
||||
broadcastClient.OnBroadcastRecived += BroadcastClient_OnBroadcastRecived;
|
||||
@@ -116,7 +131,7 @@ internal class Program
|
||||
|
||||
if (success)
|
||||
{
|
||||
hostsManager.Add(new NetworkSocket(recivedEventArgs.IPEndPoint.Address.ToString(), remotePort));
|
||||
hostsManager.Add(new NetworkSocket(recivedEventArgs.IPEndPoint.Address.ToString(), remotePort, DateTime.Now));
|
||||
try
|
||||
{
|
||||
await NetworkClient.SendAsync(recivedEventArgs.IPEndPoint.Address, remotePort, "DiscoverAnswer", hostsToSend);
|
||||
@@ -170,7 +185,7 @@ internal class Program
|
||||
{
|
||||
try
|
||||
{
|
||||
publicPort = random.Next(1000, 6000);
|
||||
PublicPort = random.Next(1000, 6000);
|
||||
|
||||
NatDiscoverer? discoverer = new NatDiscoverer();
|
||||
device = await discoverer.DiscoverDeviceAsync();
|
||||
@@ -178,11 +193,11 @@ internal class Program
|
||||
IPAddress? ip = await device.GetExternalIPAsync();
|
||||
ConsoleExt.WriteLine($"The public IP Address is: {ip} ", ConsoleColor.Green);
|
||||
|
||||
portMapping = new Mapping(Protocol.Tcp, privatePort, publicPort, "HyperbolicDowloader");
|
||||
portMapping = new Mapping(Protocol.Tcp, PrivatePort, PublicPort, "HyperbolicDowloader");
|
||||
|
||||
await device.CreatePortMapAsync(portMapping);
|
||||
|
||||
ConsoleExt.WriteLine($"The public port is: {publicPort}", ConsoleColor.Green);
|
||||
ConsoleExt.WriteLine($"The public port is: {PublicPort}", ConsoleColor.Green);
|
||||
return true;
|
||||
}
|
||||
catch (NatDeviceNotFoundException)
|
||||
@@ -192,7 +207,7 @@ internal class Program
|
||||
}
|
||||
catch (MappingException ex)
|
||||
{
|
||||
ConsoleExt.WriteLine($"An error occurred while mapping the private port ({privatePort}) to the public port ({publicPort})! Error message: {ex.Message}", ConsoleColor.Red);
|
||||
ConsoleExt.WriteLine($"An error occurred while mapping the private port ({PrivatePort}) to the public port ({PublicPort})! Error message: {ex.Message}", ConsoleColor.Red);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -226,11 +241,12 @@ internal class Program
|
||||
private static void Console_CancelKeyPress(object? sender, ConsoleCancelEventArgs e)
|
||||
{
|
||||
ClosePorts();
|
||||
hostsManager.SaveHosts();
|
||||
}
|
||||
|
||||
public static NetworkSocket? GetLocalSocket()
|
||||
{
|
||||
int port = publicPort;
|
||||
int port = PublicPort;
|
||||
string? ipAddress = null;
|
||||
|
||||
if (device is not null)
|
||||
@@ -241,7 +257,7 @@ internal class Program
|
||||
if (ipAddress is null || ipAddress == "0.0.0.0")
|
||||
{
|
||||
ipAddress = NetworkUtilities.GetIP4Adress()?.ToString();
|
||||
port = privatePort;
|
||||
port = PrivatePort;
|
||||
}
|
||||
|
||||
if (ipAddress is null)
|
||||
@@ -249,6 +265,6 @@ internal class Program
|
||||
return null;
|
||||
}
|
||||
|
||||
return new NetworkSocket(ipAddress, port);
|
||||
return new NetworkSocket(ipAddress, port, DateTime.Now);
|
||||
}
|
||||
}
|
||||
@@ -23,14 +23,20 @@ internal class InputHandler
|
||||
public InputHandler(HostsManager hostsManager, FilesManager filesManager)
|
||||
{
|
||||
this.hostsManager = hostsManager;
|
||||
commander.Register((_) => Console.Clear(), "clear");
|
||||
commander.Register(Exit, "exit");
|
||||
commander.Register((_) => Console.Clear(), "clear", "cls");
|
||||
commander.Register(Exit, "exit", "quit");
|
||||
commander.Register(ShowInfo, "info", "inf");
|
||||
commander.Register(GetFile, "get");
|
||||
|
||||
Command addCommand = commander.Register(AddFile, "add");
|
||||
addCommand.Register(AddHost, "host");
|
||||
addCommand.Register(AddFile, "file");
|
||||
commander.Register(RemoveFile, "remove");
|
||||
commander.Register(ListFiles, "list");
|
||||
|
||||
commander.Register(RemoveFile, "remove", "rm");
|
||||
|
||||
Command listCommand = commander.Register(ListFiles, "list", "ls");
|
||||
listCommand.Register(ListFiles, "files");
|
||||
listCommand.Register(ListHosts, "hosts");
|
||||
|
||||
this.filesManager = filesManager;
|
||||
}
|
||||
@@ -39,6 +45,7 @@ internal class InputHandler
|
||||
{
|
||||
while (!exit)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.Write("> ");
|
||||
Console.CursorVisible = true;
|
||||
|
||||
@@ -75,7 +82,7 @@ internal class InputHandler
|
||||
try
|
||||
{
|
||||
Console.WriteLine("Waiting for response...");
|
||||
NetworkSocket? localSocket = Program.GetLocalSocket() ?? new NetworkSocket("0.0.0.0", 0);
|
||||
NetworkSocket? localSocket = Program.GetLocalSocket() ?? new NetworkSocket("0.0.0.0", 0, DateTime.MinValue);
|
||||
List<NetworkSocket>? recivedHosts = NetworkClient.Send<List<NetworkSocket>>(ipAddress, port, "GetHostsList", localSocket);
|
||||
|
||||
if (recivedHosts is not null)
|
||||
@@ -134,10 +141,38 @@ internal class InputHandler
|
||||
Console.WriteLine($"Hash: {fileInfo.Hash}");
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.CursorTop--;
|
||||
}
|
||||
|
||||
private void ListHosts(string _)
|
||||
{
|
||||
int index = 0;
|
||||
foreach (NetworkSocket host in hostsManager.ToList())
|
||||
{
|
||||
index++;
|
||||
Console.WriteLine($"{index}) {host.IPAddress}:{host.Port}");
|
||||
Console.WriteLine($"Last active: {host.LastActive}");
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.CursorTop--;
|
||||
}
|
||||
|
||||
private void ShowInfo(string _)
|
||||
{
|
||||
if (Program.PublicIpAddress is not null)
|
||||
{
|
||||
ConsoleExt.WriteLine($"The public IP Address is: {Program.PublicIpAddress}", ConsoleColor.Green);
|
||||
ConsoleExt.WriteLine($"The public port is: {Program.PublicPort}", ConsoleColor.Green);
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
ConsoleExt.WriteLine($"The private IP Address is: {NetworkUtilities.GetIP4Adress()}", ConsoleColor.Green);
|
||||
ConsoleExt.WriteLine($"The private port is: {Program.PrivatePort}", ConsoleColor.Green);
|
||||
}
|
||||
|
||||
private void Exit(string _)
|
||||
{
|
||||
hostsManager.SaveHosts();
|
||||
exit = true;
|
||||
}
|
||||
|
||||
@@ -177,10 +212,13 @@ internal class InputHandler
|
||||
}
|
||||
else if (!sendTask.Result)
|
||||
{
|
||||
host.LastActive = DateTime.Now;
|
||||
ConsoleExt.WriteLine($"{host.IPAddress}:{host.Port} > Does not have the requested file", ConsoleColor.Red);
|
||||
continue;
|
||||
}
|
||||
|
||||
host.LastActive = DateTime.Now;
|
||||
|
||||
ConsoleExt.WriteLine($"{host.IPAddress}:{host.Port} > Has the requested file", ConsoleColor.Green);
|
||||
Console.WriteLine("Requesting file...");
|
||||
|
||||
@@ -256,12 +294,12 @@ internal class InputHandler
|
||||
unitsPerSecond = (unitsPerSecond + bytesInOneSecond) / 2;
|
||||
if (unitsPerSecond > 125000)
|
||||
{
|
||||
unitsPerSecond = unitsPerSecond / 125000;
|
||||
unitsPerSecond /= 125000;
|
||||
unit = "Mb";
|
||||
}
|
||||
else
|
||||
{
|
||||
unitsPerSecond = unitsPerSecond / 125;
|
||||
unitsPerSecond /= 125;
|
||||
unit = "Kb";
|
||||
}
|
||||
bytesInOneSecond = 0;
|
||||
@@ -291,6 +329,7 @@ internal class InputHandler
|
||||
Console.WriteLine($"File saved at: {Path.GetFullPath($"./Downloads/{fileName}")}");
|
||||
ConsoleExt.WriteLine("Done", ConsoleColor.Green);
|
||||
stopWatch.Stop();
|
||||
hostsManager.SaveHosts();
|
||||
return;
|
||||
}
|
||||
else
|
||||
@@ -299,5 +338,6 @@ internal class InputHandler
|
||||
}
|
||||
}
|
||||
ConsoleExt.WriteLine("None of the available hosts have the requested file!", ConsoleColor.Red);
|
||||
hostsManager.SaveHosts();
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ internal static class Setup
|
||||
try
|
||||
{
|
||||
Console.WriteLine("Waiting for response...");
|
||||
NetworkSocket? localSocket = Program.GetLocalSocket() ?? new NetworkSocket("0.0.0.0", 0);
|
||||
NetworkSocket? localSocket = Program.GetLocalSocket() ?? new NetworkSocket("0.0.0.0", 0, DateTime.MinValue);
|
||||
List<NetworkSocket>? recivedHosts = await NetworkClient.SendAsync<List<NetworkSocket>>(ipAddress, port, "GetHostsList", localSocket);
|
||||
|
||||
if (recivedHosts is not null)
|
||||
|
||||
Reference in New Issue
Block a user