diff --git a/Tanji.CLI/Program.cs b/Tanji.CLI/Program.cs index f030e84..074f4ea 100644 --- a/Tanji.CLI/Program.cs +++ b/Tanji.CLI/Program.cs @@ -46,10 +46,13 @@ static void CleanUp(PosixSignalContext context) private readonly ILogger _logger; private readonly IWebInterceptionService _webInterception; - private readonly IConnectionHandlerService _connectionHandler; private readonly IClientHandlerService _clientHandler; + private readonly IConnectionHandlerService _connectionHandler; - public Program(ILogger logger, IWebInterceptionService webInterception, IClientHandlerService clientHandler, IConnectionHandlerService connectionHandler) + public Program(ILogger logger, + IWebInterceptionService webInterception, + IClientHandlerService clientHandler, + IConnectionHandlerService connectionHandler) { _logger = logger; _clientHandler = clientHandler; @@ -71,7 +74,7 @@ public async Task RunAsync(CancellationToken cancellationToken = default) _logger.LogInformation("Client Processed : {game.path}", game.Path); var connectionContext = new HConnectionContext(game); - HConnection connection = await _connectionHandler.LaunchAndInterceptConnectionAsync(ticket, connectionContext, cancellationToken).ConfigureAwait(false); + HConnection connection = await _connectionHandler.LaunchAndInterceptConnectionAsync(ticket, connectionContext, cancellationToken).ConfigureAwait(false); await connection.WeldNodesAsync(cancellationToken).ConfigureAwait(false); } diff --git a/Tanji.Core/API/IInstaller.cs b/Tanji.Core/API/IInstaller.cs index cee57c4..2aeb8f6 100644 --- a/Tanji.Core/API/IInstaller.cs +++ b/Tanji.Core/API/IInstaller.cs @@ -1,4 +1,5 @@ -using Tanji.Core.Habbo.Canvas; +using Tanji.Core.Services; +using Tanji.Core.Habbo.Canvas; using Tanji.Core.Habbo.Network; namespace Tanji.Core.API; @@ -6,5 +7,5 @@ namespace Tanji.Core.API; public interface IInstaller { IGame Game { get; } - IHConnection Connection { get; } + IHConnection Connection { get; } } \ No newline at end of file diff --git a/Tanji.Core/Habbo/Network/IHConnection.cs b/Tanji.Core/Habbo/Network/IHConnection.cs index 7e7cdf3..b9f6f9f 100644 --- a/Tanji.Core/Habbo/Network/IHConnection.cs +++ b/Tanji.Core/Habbo/Network/IHConnection.cs @@ -1,10 +1,14 @@ -namespace Tanji.Core.Habbo.Network; +using Tanji.Core.Services; -public interface IHConnection +namespace Tanji.Core.Habbo.Network; + +public interface IHConnection where TMiddleman : IPacketMiddlemanService { HNode? Local { get; } HNode? Remote { get; } Incoming? In { get; } Outgoing? Out { get; } + + TMiddleman? Middleman { get; } } \ No newline at end of file diff --git a/Tanji.Core/Network/HConnection.cs b/Tanji.Core/Network/HConnection.cs index dba794e..37ea9b0 100644 --- a/Tanji.Core/Network/HConnection.cs +++ b/Tanji.Core/Network/HConnection.cs @@ -3,6 +3,7 @@ using System.Net.Sockets; using Tanji.Core.Habbo; +using Tanji.Core.Services; using Tanji.Core.Habbo.Network; using CommunityToolkit.HighPerformance.Buffers; @@ -12,7 +13,7 @@ namespace Tanji.Core.Network; /// /// Represents a reusable 'bridge' that transfers data to/from two separate instances. /// -public sealed class HConnection : IHConnection +public sealed class HConnection : IHConnection where TMiddleman : IPacketMiddlemanService { private static ReadOnlySpan XDPRequestBytes => "\0"u8; private static readonly ReadOnlyMemory XDPResponseBytes = Encoding.UTF8.GetBytes("\0"); @@ -25,12 +26,21 @@ public sealed class HConnection : IHConnection public Incoming? In { get; set; } public Outgoing? Out { get; set; } + public TMiddleman? Middleman { get; } public bool IsConnected => Local != null && Remote != null && Local.IsConnected & Remote.IsConnected; + public HConnection() + : this(default) + { } + public HConnection(TMiddleman? middleman) + { + Middleman = middleman; + } + public Task WeldNodesAsync(CancellationToken cancellationToken = default) { - Task localToRemote = WeldNodesAsync(Local!, Remote!, true, cancellationToken); - Task remoteToLocal = WeldNodesAsync(Remote!, Local!, false, cancellationToken); + Task localToRemote = WeldNodesAsync(Local!, Remote!, Middleman, true, cancellationToken); + Task remoteToLocal = WeldNodesAsync(Remote!, Local!, Middleman, false, cancellationToken); return Task.WhenAll(localToRemote, remoteToLocal); } public async ValueTask InterceptLocalConnectionAsync(HConnectionContext context, CancellationToken cancellationToken = default) @@ -164,7 +174,8 @@ private static async ValueTask ConnectAsync(EndPoint remoteEndPoint, Can } return socket; } - private static async Task WeldNodesAsync(HNode source, HNode destination, bool isOutbound, CancellationToken cancellationToken = default) + + private static async Task WeldNodesAsync(HNode source, HNode destination, TMiddleman? middleman, bool isOutbound, CancellationToken cancellationToken = default) { while (source.IsConnected && destination.IsConnected && !cancellationToken.IsCancellationRequested) { @@ -173,16 +184,26 @@ private static async Task WeldNodesAsync(HNode source, HNode destination, bool i _ = await source.ReceivePacketAsync(bufferWriter, cancellationToken).ConfigureAwait(false); // Continuously attempt to receive packets from the node - _ = TransferPacketAsync(destination, bufferWriter, isOutbound, cancellationToken); + _ = TransferPacketAsync(destination, bufferWriter, middleman, isOutbound, cancellationToken); } } - private static async Task TransferPacketAsync(HNode destination, ArrayPoolBufferWriter bufferWriter, bool isOutbound, CancellationToken cancellationToken = default) + private static async Task TransferPacketAsync(HNode destination, ArrayPoolBufferWriter bufferWriter, TMiddleman? middleman, bool isOutbound, CancellationToken cancellationToken = default) { try { if (bufferWriter.WrittenCount == 0) return; Memory mutableBuffer = bufferWriter.DangerousGetArray(); + if (middleman != null) + { + ValueTask packetProcessTask = isOutbound + ? middleman.PacketOutboundAsync(mutableBuffer) + : middleman.PacketInboundAsync(mutableBuffer); + + // If true, the packet is to be ignored/blocked + if (await packetProcessTask.ConfigureAwait(false)) return; + } + await destination.SendPacketAsync(mutableBuffer, cancellationToken).ConfigureAwait(false); } finally { bufferWriter.Dispose(); } diff --git a/Tanji.Core/Network/IPacketMiddleman.cs b/Tanji.Core/Network/IPacketMiddleman.cs deleted file mode 100644 index ac932f5..0000000 --- a/Tanji.Core/Network/IPacketMiddleman.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Tanji.Core.Network; - -public interface IPacketMiddleman -{ - -} \ No newline at end of file diff --git a/Tanji.Core/ServiceCollectionExtensions.cs b/Tanji.Core/ServiceCollectionExtensions.cs index b680adb..071f33a 100644 --- a/Tanji.Core/ServiceCollectionExtensions.cs +++ b/Tanji.Core/ServiceCollectionExtensions.cs @@ -18,9 +18,11 @@ public static IServiceCollection AddTanjiCore(this IServiceCollection services) // Services services.AddSingleton(); - services.AddSingleton(); services.AddSingleton, ClientHandlerService>(); + services.AddSingleton(); + services.AddSingleton, ConnectionHandlerService>(); + // Add view-models services.AddSingleton(); services.AddSingleton(); diff --git a/Tanji.Core/Services/IConnectionHandlerService.cs b/Tanji.Core/Services/IConnectionHandlerService.cs index 50102c3..261c781 100644 --- a/Tanji.Core/Services/IConnectionHandlerService.cs +++ b/Tanji.Core/Services/IConnectionHandlerService.cs @@ -4,9 +4,9 @@ namespace Tanji.Core.Services; -public interface IConnectionHandlerService +public interface IConnectionHandlerService where TPacketMiddleman : IPacketMiddlemanService { - ObservableCollection Connections { get; } + ObservableCollection> Connections { get; } - Task LaunchAndInterceptConnectionAsync(string ticket, HConnectionContext options, CancellationToken cancellationToken = default); + Task> LaunchAndInterceptConnectionAsync(string ticket, HConnectionContext options, CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/Tanji.Core/Services/IPacketMiddlemanService.cs b/Tanji.Core/Services/IPacketMiddlemanService.cs new file mode 100644 index 0000000..8735e2c --- /dev/null +++ b/Tanji.Core/Services/IPacketMiddlemanService.cs @@ -0,0 +1,7 @@ +namespace Tanji.Core.Services; + +public interface IPacketMiddlemanService +{ + ValueTask PacketInboundAsync(Memory buffer); + ValueTask PacketOutboundAsync(Memory buffer); +} \ No newline at end of file diff --git a/Tanji.Core/Services/Implementations/ConnectionHandlerService.cs b/Tanji.Core/Services/Implementations/ConnectionHandlerService.cs index 5000163..568b2a6 100644 --- a/Tanji.Core/Services/Implementations/ConnectionHandlerService.cs +++ b/Tanji.Core/Services/Implementations/ConnectionHandlerService.cs @@ -12,20 +12,24 @@ namespace Tanji.Core.Services; -public sealed class ConnectionHandlerService : IConnectionHandlerService +public sealed class ConnectionHandlerService : IConnectionHandlerService { + private readonly PacketMiddlemanService _packetMiddleman; private readonly ILogger _logger; private readonly IClientHandlerService _clientHandler; - public ObservableCollection Connections { get; } = []; + public ObservableCollection> Connections { get; } = []; - public ConnectionHandlerService(ILogger logger, IClientHandlerService clientHandler) + public ConnectionHandlerService(ILogger logger, + IClientHandlerService clientHandler, + PacketMiddlemanService packetMiddleman) { _logger = logger; _clientHandler = clientHandler; + _packetMiddleman = packetMiddleman; } - public async Task LaunchAndInterceptConnectionAsync(string ticket, HConnectionContext context, CancellationToken cancellationToken = default) + public async Task> LaunchAndInterceptConnectionAsync(string ticket, HConnectionContext context, CancellationToken cancellationToken = default) { if (string.IsNullOrWhiteSpace(ticket)) { @@ -33,7 +37,7 @@ public async Task LaunchAndInterceptConnectionAsync(string ticket, ThrowHelper.ThrowArgumentNullException(nameof(ticket)); } - var connection = new HConnection(); + var connection = new HConnection(_packetMiddleman); ValueTask interceptLocalConnectionTask = connection.InterceptLocalConnectionAsync(context, cancellationToken); _ = _clientHandler.LaunchClient(context.Platform, ticket, context.ClientPath); diff --git a/Tanji.Core/Services/Implementations/PacketMiddlemanService.cs b/Tanji.Core/Services/Implementations/PacketMiddlemanService.cs new file mode 100644 index 0000000..abc291f --- /dev/null +++ b/Tanji.Core/Services/Implementations/PacketMiddlemanService.cs @@ -0,0 +1,13 @@ +namespace Tanji.Core.Services; + +public class PacketMiddlemanService : IPacketMiddlemanService +{ + public ValueTask PacketInboundAsync(Memory buffer) + { + throw new NotImplementedException(); + } + public ValueTask PacketOutboundAsync(Memory buffer) + { + throw new NotImplementedException(); + } +} \ No newline at end of file