From 12e8d20913473e4c044e11e9460fd0c7b7bb3d0c Mon Sep 17 00:00:00 2001 From: Rutherther Date: Tue, 31 Jan 2023 12:57:46 +0100 Subject: [PATCH] feat: add a console sample logging all received and sent packets from nostale process --- .../ConsolePacketLogger/ClientService.cs | 97 +++++++++++++++++++ .../ConsolePacketLogger.csproj | 29 ++++++ .../EveryPacketResponder.cs | 24 +++++ .../PacketLoggerOptions.cs | 18 ++++ src/Samples/ConsolePacketLogger/Program.cs | 75 ++++++++++++++ src/Samples/ConsolePacketLogger/app.manifest | 11 +++ 6 files changed, 254 insertions(+) create mode 100644 src/Samples/ConsolePacketLogger/ClientService.cs create mode 100644 src/Samples/ConsolePacketLogger/ConsolePacketLogger.csproj create mode 100644 src/Samples/ConsolePacketLogger/EveryPacketResponder.cs create mode 100644 src/Samples/ConsolePacketLogger/PacketLoggerOptions.cs create mode 100644 src/Samples/ConsolePacketLogger/Program.cs create mode 100644 src/Samples/ConsolePacketLogger/app.manifest diff --git a/src/Samples/ConsolePacketLogger/ClientService.cs b/src/Samples/ConsolePacketLogger/ClientService.cs new file mode 100644 index 0000000..53211e1 --- /dev/null +++ b/src/Samples/ConsolePacketLogger/ClientService.cs @@ -0,0 +1,97 @@ +// +// ClientService.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Diagnostics; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using NosSmooth.Comms.Core; +using NosSmooth.Comms.Data.Messages; +using NosSmooth.Comms.Local; +using NosSmooth.Core.Contracts; +using NosSmooth.Core.Extensions; +using NosSmooth.PacketSerializer.Extensions; +using NosSmooth.PacketSerializer.Packets; + +namespace ConsolePacketLogger; + +/// +public class ClientService : BackgroundService +{ + private readonly IPacketTypesRepository _packetTypesRepository; + private readonly CommsInjector _injector; + private readonly IHostApplicationLifetime _lifetime; + private readonly ILogger _logger; + private readonly PacketLoggerOptions _options; + + /// + /// Initializes a new instance of the class. + /// + /// The packet types repository. + /// The injector. + /// The lifetime. + /// The logger. + /// The options. + public ClientService + ( + IPacketTypesRepository packetTypesRepository, + CommsInjector injector, + IHostApplicationLifetime lifetime, + ILogger logger, + IOptions options + ) + { + _packetTypesRepository = packetTypesRepository; + _injector = injector; + _lifetime = lifetime; + _logger = logger; + _options = options.Value; + } + + /// + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + var packetsResult = _packetTypesRepository.AddDefaultPackets(); + if (!packetsResult.IsSuccess) + { + _logger.LogResultError(packetsResult); + } + + var process = Process.GetProcessById(_options.ProcessId); + var connectionResult = await _injector.EstablishNamedPipesConnectionAsync + (process, stoppingToken, stoppingToken); + if (!connectionResult.IsDefined(out var connection)) + { + _logger.LogResultError(connectionResult); + _lifetime.StopApplication(); + return; + } + + var handshakeResponseResult = await connection.Connection + .ContractHanshake(new HandshakeRequest("ConsolePacketLogger example", true, false)) + .WaitForAsync(DefaultStates.ResponseObtained, ct: stoppingToken); + + if (!handshakeResponseResult.IsDefined(out var handshakeResponse)) + { + _logger.LogResultError(handshakeResponseResult); + _lifetime.StopApplication(); + return; + } + + _logger.LogInformation + ( + $"Connected to {handshakeResponse.CharacterName ?? "Not in game"} ({handshakeResponse.CharacterId?.ToString() ?? "Not in game"})" + ); + + var runResult = await connection.Connection.RunHandlerAsync(stoppingToken); + if (!runResult.IsSuccess) + { + _logger.LogResultError(runResult); + } + + _lifetime.StopApplication(); + } +} \ No newline at end of file diff --git a/src/Samples/ConsolePacketLogger/ConsolePacketLogger.csproj b/src/Samples/ConsolePacketLogger/ConsolePacketLogger.csproj new file mode 100644 index 0000000..8855e69 --- /dev/null +++ b/src/Samples/ConsolePacketLogger/ConsolePacketLogger.csproj @@ -0,0 +1,29 @@ + + + + Exe + net7.0 + enable + enable + app.manifest + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Samples/ConsolePacketLogger/EveryPacketResponder.cs b/src/Samples/ConsolePacketLogger/EveryPacketResponder.cs new file mode 100644 index 0000000..6b65cc2 --- /dev/null +++ b/src/Samples/ConsolePacketLogger/EveryPacketResponder.cs @@ -0,0 +1,24 @@ +// +// EveryPacketResponder.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Core.Packets; +using NosSmooth.Packets; +using NosSmooth.PacketSerializer.Abstractions.Attributes; +using Remora.Results; + +namespace ConsolePacketLogger; + +/// +public class EveryPacketResponder : IEveryPacketResponder +{ + /// + public Task Respond(PacketEventArgs packetArgs, CancellationToken ct = default) + where TPacket : IPacket + { + Console.WriteLine((packetArgs.Source == PacketSource.Server ? "[Recv]\t" : "[Sent]\t") + packetArgs.PacketString); + return Task.FromResult(Result.FromSuccess()); + } +} \ No newline at end of file diff --git a/src/Samples/ConsolePacketLogger/PacketLoggerOptions.cs b/src/Samples/ConsolePacketLogger/PacketLoggerOptions.cs new file mode 100644 index 0000000..cd1e485 --- /dev/null +++ b/src/Samples/ConsolePacketLogger/PacketLoggerOptions.cs @@ -0,0 +1,18 @@ +// +// PacketLoggerOptions.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace ConsolePacketLogger; + +/// +/// Options telling the process to inject into. +/// +public class PacketLoggerOptions +{ + /// + /// Gets or sets the id of the process to connect to. + /// + public int ProcessId { get; set; } +} \ No newline at end of file diff --git a/src/Samples/ConsolePacketLogger/Program.cs b/src/Samples/ConsolePacketLogger/Program.cs new file mode 100644 index 0000000..7cf35e3 --- /dev/null +++ b/src/Samples/ConsolePacketLogger/Program.cs @@ -0,0 +1,75 @@ +// +// Program.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using ConsolePacketLogger; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using NosSmooth.Comms.Core.Extensions; +using NosSmooth.Comms.Local; +using NosSmooth.Comms.Local.Extensions; +using NosSmooth.Core.Extensions; +using NosSmooth.Data.Abstractions; +using NosSmooth.LocalBinding; +using Spectre.Console; + +/// +/// A class with main. +/// +public static class Program +{ + /// + /// A main. + /// + /// A representing the asynchronous operation. + public static async Task Main() + { + var processInitResults = CommsInjector.CreateNostaleProcesssesBrowsers().ToArray(); + + if (processInitResults.Length == 0) + { + Console.WriteLine("Could not find any NosTale processes."); + return; + } + + foreach (var initResult in processInitResults.Where(x => !x.IsSuccess)) + { + Console.WriteLine($"There was an error initializing browser manager for a process."); + Console.WriteLine(initResult.ToFullString()); + } + + var nostaleProcesses = processInitResults.Where(x => x.IsSuccess).Select(x => x.Entity); + + var selectedProcess = AnsiConsole.Prompt + ( + new SelectionPrompt() + .Title("Choose NosTale process to log packets from.") + .UseConverter + ( + x => x.IsInGame + ? $"{x.PlayerManager.Player.Name} ({x.Process.ProcessName} - {x.Process.Id})" + : $"Not in game ({x.Process.ProcessName} - {x.Process.Id})" + ) + .AddChoices(nostaleProcesses) + ); + + var host = new HostBuilder() + .ConfigureLogging(b => b.ClearProviders().AddConsole()) + .ConfigureServices + ( + s => s + .Configure(o => o.ProcessId = selectedProcess.Process.Id) + .AddNostaleCore() + .AddSingleClientHandling() + .AddLocalComms() + .AddHostedService() + .AddPacketResponder() + ) + .Build(); + + await host.RunAsync(); + } +} \ No newline at end of file diff --git a/src/Samples/ConsolePacketLogger/app.manifest b/src/Samples/ConsolePacketLogger/app.manifest new file mode 100644 index 0000000..2d1ae73 --- /dev/null +++ b/src/Samples/ConsolePacketLogger/app.manifest @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file -- 2.48.1