mirror of
https://github.com/Stone-Red-Code/HyperbolicDownloader.git
synced 2026-09-07 23:40:52 +02:00
- Order hosts by last active
- Remove `Setup.cs` file - Add discover command - Increase request timeout when downloading a file to avoid errors - Better exception handling for file up/down-loading
This commit is contained in:
@@ -24,13 +24,11 @@ internal static class FileCompressor
|
|||||||
{
|
{
|
||||||
byte[] buffer = new byte[chunkSize];
|
byte[] buffer = new byte[chunkSize];
|
||||||
int bytesRead;
|
int bytesRead;
|
||||||
using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read))
|
using FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
using (BufferedStream bs = new BufferedStream(fs))
|
using BufferedStream bs = new BufferedStream(fs);
|
||||||
|
while ((bytesRead = bs.Read(buffer, 0, chunkSize)) != 0)
|
||||||
{
|
{
|
||||||
while ((bytesRead = bs.Read(buffer, 0, chunkSize)) != 0)
|
yield return buffer;
|
||||||
{
|
|
||||||
yield return buffer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@ namespace HyperbolicDownloader;
|
|||||||
|
|
||||||
internal class HostsManager
|
internal class HostsManager
|
||||||
{
|
{
|
||||||
private readonly List<NetworkSocket> hosts = new List<NetworkSocket>();
|
private List<NetworkSocket> hosts = new List<NetworkSocket>();
|
||||||
public int Count => hosts.Count;
|
public int Count => hosts.Count;
|
||||||
|
|
||||||
public void AddRange(IEnumerable<NetworkSocket> hosts)
|
public void AddRange(IEnumerable<NetworkSocket> hosts)
|
||||||
@@ -98,6 +98,7 @@ internal class HostsManager
|
|||||||
|
|
||||||
public void SaveHosts()
|
public void SaveHosts()
|
||||||
{
|
{
|
||||||
|
hosts = hosts.OrderByDescending(h => h.LastActive).ToList();
|
||||||
File.WriteAllText(Program.HostsFilePath, JsonSerializer.Serialize(hosts));
|
File.WriteAllText(Program.HostsFilePath, JsonSerializer.Serialize(hosts));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using HyperbolicDownloader.FileProcessing;
|
using HyperbolicDownloader.FileProcessing;
|
||||||
|
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -155,44 +156,51 @@ namespace HyperbolicDownloader.Networking
|
|||||||
|
|
||||||
private async Task Upload(TcpClient client, string hash)
|
private async Task Upload(TcpClient client, string hash)
|
||||||
{
|
{
|
||||||
byte[] bytesToSend;
|
try
|
||||||
hash = hash.Trim();
|
|
||||||
NetworkStream nwStream = client.GetStream();
|
|
||||||
client.SendBufferSize = 64000;
|
|
||||||
if (filesManager.TryGet(hash, out HyperFileInfo? hyperFileInfo) && File.Exists(hyperFileInfo?.FilePath))
|
|
||||||
{
|
{
|
||||||
if (hash != await FileValidator.CalculateHashAsync(hyperFileInfo.FilePath))
|
byte[] bytesToSend;
|
||||||
|
hash = hash.Trim();
|
||||||
|
NetworkStream nwStream = client.GetStream();
|
||||||
|
client.SendBufferSize = 64000;
|
||||||
|
if (filesManager.TryGet(hash, out HyperFileInfo? hyperFileInfo) && File.Exists(hyperFileInfo?.FilePath))
|
||||||
{
|
{
|
||||||
bytesToSend = Encoding.ASCII.GetBytes("Hash does not match!");
|
if (hash != await FileValidator.CalculateHashAsync(hyperFileInfo.FilePath))
|
||||||
await nwStream.WriteAsync(bytesToSend);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//string compressedFilePath = $"{hash + DateTime.Now.Millisecond}.temp";
|
|
||||||
|
|
||||||
//FileCompressor.CompressFile(hyperFileInfo.FilePath, compressedFilePath);
|
|
||||||
|
|
||||||
FileInfo compressedFileInfo = new FileInfo(hyperFileInfo.FilePath);
|
|
||||||
|
|
||||||
bytesToSend = Encoding.ASCII.GetBytes($"{compressedFileInfo.Length}/{Path.GetFileName(hyperFileInfo.FilePath)}");
|
|
||||||
await nwStream.WriteAsync(bytesToSend);
|
|
||||||
|
|
||||||
foreach (byte[]? chunk in FileCompressor.ReadChunks(hyperFileInfo.FilePath, 64000))
|
|
||||||
{
|
|
||||||
if (chunk is not null)
|
|
||||||
{
|
{
|
||||||
await nwStream.WriteAsync(chunk);
|
bytesToSend = Encoding.ASCII.GetBytes("Hash does not match!");
|
||||||
|
await nwStream.WriteAsync(bytesToSend);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// File.Delete(compressedFilePath);
|
//string compressedFilePath = $"{hash + DateTime.Now.Millisecond}.temp";
|
||||||
|
|
||||||
|
//FileCompressor.CompressFile(hyperFileInfo.FilePath, compressedFilePath);
|
||||||
|
|
||||||
|
FileInfo compressedFileInfo = new FileInfo(hyperFileInfo.FilePath);
|
||||||
|
|
||||||
|
bytesToSend = Encoding.ASCII.GetBytes($"{compressedFileInfo.Length}/{Path.GetFileName(hyperFileInfo.FilePath)}");
|
||||||
|
await nwStream.WriteAsync(bytesToSend);
|
||||||
|
|
||||||
|
foreach (byte[]? chunk in FileCompressor.ReadChunks(hyperFileInfo.FilePath, 64000))
|
||||||
|
{
|
||||||
|
if (chunk is not null)
|
||||||
|
{
|
||||||
|
await nwStream.WriteAsync(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// File.Delete(compressedFilePath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bytesToSend = Encoding.ASCII.GetBytes("File not found!");
|
||||||
|
await nwStream.WriteAsync(bytesToSend);
|
||||||
|
}
|
||||||
|
client.Close();
|
||||||
}
|
}
|
||||||
else
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
bytesToSend = Encoding.ASCII.GetBytes("File not found!");
|
Debug.WriteLine(ex);
|
||||||
await nwStream.WriteAsync(bytesToSend);
|
|
||||||
}
|
}
|
||||||
client.Close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StopListening()
|
public void StopListening()
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace HyperbolicDownloader;
|
|||||||
|
|
||||||
internal class Program
|
internal class Program
|
||||||
{
|
{
|
||||||
private const int BroadcastPort = 2155;
|
public const int BroadcastPort = 2155;
|
||||||
public const string HostsFilePath = "Hosts.json";
|
public const string HostsFilePath = "Hosts.json";
|
||||||
public const string FilesInfoPath = "Files.json";
|
public const string FilesInfoPath = "Files.json";
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ internal class Program
|
|||||||
|
|
||||||
Console.WriteLine("Running local discovery routine...");
|
Console.WriteLine("Running local discovery routine...");
|
||||||
BroadcastClient.Send(BroadcastPort, PrivatePort.ToString());
|
BroadcastClient.Send(BroadcastPort, PrivatePort.ToString());
|
||||||
await Task.Delay(5000);
|
await Task.Delay(3000);
|
||||||
|
|
||||||
int activeHostsCount = 0;
|
int activeHostsCount = 0;
|
||||||
if (hostsManager.Count > 0)
|
if (hostsManager.Count > 0)
|
||||||
@@ -96,9 +96,8 @@ internal class Program
|
|||||||
|
|
||||||
if (activeHostsCount == 0)
|
if (activeHostsCount == 0)
|
||||||
{
|
{
|
||||||
hostsManager.AddRange(await Setup.ConfigureHost());
|
ConsoleExt.WriteLine("No active hosts found!", ConsoleColor.Red);
|
||||||
Console.WriteLine("Checking if hosts are active...");
|
ConsoleExt.WriteLine("Use 'add host xxx.xxx.xxx.xxx:yyyy' to add a new host.", ConsoleColor.Red);
|
||||||
activeHostsCount = hostsManager.CheckHostsActivity();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine($"{hostsManager.Count} known host(s).");
|
Console.WriteLine($"{hostsManager.Count} known host(s).");
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ internal class InputHandler
|
|||||||
commander.Register((_) => Console.Clear(), "clear", "cls");
|
commander.Register((_) => Console.Clear(), "clear", "cls");
|
||||||
commander.Register(Exit, "exit", "quit");
|
commander.Register(Exit, "exit", "quit");
|
||||||
commander.Register(ShowInfo, "info", "inf");
|
commander.Register(ShowInfo, "info", "inf");
|
||||||
|
commander.Register(Discover, "discover", "disc");
|
||||||
commander.Register(GetFile, "get");
|
commander.Register(GetFile, "get");
|
||||||
|
|
||||||
Command addCommand = commander.Register(AddFile, "add");
|
Command addCommand = commander.Register(AddFile, "add");
|
||||||
@@ -38,7 +39,7 @@ internal class InputHandler
|
|||||||
listCommand.Register(ListFiles, "files");
|
listCommand.Register(ListFiles, "files");
|
||||||
listCommand.Register(ListHosts, "hosts");
|
listCommand.Register(ListHosts, "hosts");
|
||||||
|
|
||||||
commander.Register((_) => hostsManager.CheckHostsActivity(), "status", "check");
|
commander.Register(CheckActiveHosts, "status", "check");
|
||||||
|
|
||||||
this.filesManager = filesManager;
|
this.filesManager = filesManager;
|
||||||
}
|
}
|
||||||
@@ -101,6 +102,10 @@ internal class InputHandler
|
|||||||
{
|
{
|
||||||
ConsoleExt.WriteLine($"Invalid host! Error message: {ex.Message}", ConsoleColor.Red);
|
ConsoleExt.WriteLine($"Invalid host! Error message: {ex.Message}", ConsoleColor.Red);
|
||||||
}
|
}
|
||||||
|
catch (IOException ex)
|
||||||
|
{
|
||||||
|
ConsoleExt.WriteLine($"Invalid host! Error message: {ex.Message}", ConsoleColor.Red);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -172,6 +177,26 @@ internal class InputHandler
|
|||||||
ConsoleExt.WriteLine($"The private port is: {Program.PrivatePort}", ConsoleColor.Green);
|
ConsoleExt.WriteLine($"The private port is: {Program.PrivatePort}", ConsoleColor.Green);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Discover(string _)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Running local discovery routine...");
|
||||||
|
BroadcastClient.Send(Program.BroadcastPort, Program.PrivatePort.ToString());
|
||||||
|
Thread.Sleep(3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckActiveHosts(string _)
|
||||||
|
{
|
||||||
|
int activeHostsCount = hostsManager.CheckHostsActivity();
|
||||||
|
if (activeHostsCount == 0)
|
||||||
|
{
|
||||||
|
ConsoleExt.WriteLine("No active hosts found!", ConsoleColor.Red);
|
||||||
|
ConsoleExt.WriteLine("Use 'add host xxx.xxx.xxx.xxx:yyyy' to add a new host.", ConsoleColor.Red);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"{hostsManager.Count} known host(s).");
|
||||||
|
Console.WriteLine($"{activeHostsCount} active host(s).");
|
||||||
|
}
|
||||||
|
|
||||||
private void Exit(string _)
|
private void Exit(string _)
|
||||||
{
|
{
|
||||||
hostsManager.SaveHosts();
|
hostsManager.SaveHosts();
|
||||||
@@ -236,8 +261,19 @@ internal class InputHandler
|
|||||||
|
|
||||||
byte[] bytesToSend = Encoding.ASCII.GetBytes($"Download {hash}");
|
byte[] bytesToSend = Encoding.ASCII.GetBytes($"Download {hash}");
|
||||||
nwStream.Write(bytesToSend);
|
nwStream.Write(bytesToSend);
|
||||||
nwStream.ReadTimeout = 5000;
|
nwStream.ReadTimeout = 30000;
|
||||||
int bytesRead = nwStream.Read(buffer, 0, tcpClient.ReceiveBufferSize);
|
|
||||||
|
int bytesRead;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bytesRead = nwStream.Read(buffer, 0, tcpClient.ReceiveBufferSize);
|
||||||
|
}
|
||||||
|
catch (IOException)
|
||||||
|
{
|
||||||
|
Console.WriteLine();
|
||||||
|
ConsoleExt.WriteLine("Lost connection to other host!", ConsoleColor.Red);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
string dataReceived = Encoding.ASCII.GetString(buffer, 0, bytesRead);
|
string dataReceived = Encoding.ASCII.GetString(buffer, 0, bytesRead);
|
||||||
|
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
using HyperbolicDownloader.Networking;
|
|
||||||
|
|
||||||
using Stone_Red_Utilities.ConsoleExtentions;
|
|
||||||
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
|
|
||||||
namespace HyperbolicDownloader.UserInterface;
|
|
||||||
|
|
||||||
internal static class Setup
|
|
||||||
{
|
|
||||||
public static async Task<List<NetworkSocket>> ConfigureHost()
|
|
||||||
{
|
|
||||||
ConsoleExt.WriteLine("No active hosts found!", ConsoleColor.Red);
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Console.WriteLine();
|
|
||||||
Console.CursorVisible = true;
|
|
||||||
Console.Write("Please enter an IP address manually: ");
|
|
||||||
string? ipAddressInput = Console.ReadLine();
|
|
||||||
|
|
||||||
Console.Write("Please enter an port number manually: ");
|
|
||||||
string? portInput = Console.ReadLine();
|
|
||||||
Console.CursorVisible = false;
|
|
||||||
|
|
||||||
_ = int.TryParse(portInput, out int port);
|
|
||||||
if (port < 1000 || port >= 6000)
|
|
||||||
{
|
|
||||||
ConsoleExt.WriteLine("Invalid port number!", ConsoleColor.Red);
|
|
||||||
}
|
|
||||||
else if (IPAddress.TryParse(ipAddressInput, out IPAddress? ipAddress))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Console.WriteLine("Waiting for response...");
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
ConsoleExt.WriteLine($"Success! Added {recivedHosts.Count} new host(s).", ConsoleColor.Green);
|
|
||||||
return recivedHosts;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ConsoleExt.WriteLine($"Invalid response!", ConsoleColor.Red);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (SocketException ex)
|
|
||||||
{
|
|
||||||
ConsoleExt.WriteLine($"Invalid host! Error message: {ex.Message}", ConsoleColor.Red);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ConsoleExt.WriteLine("Invalid IP address!", ConsoleColor.Red);
|
|
||||||
}
|
|
||||||
} while (true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user