// // 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.Inject.Messages; using NosSmooth.Comms.Local; using NosSmooth.Comms.Local.Extensions; using NosSmooth.Core.Contracts; using NosSmooth.Core.Extensions; using NosSmooth.LocalBinding.Options; using NosSmooth.PacketSerializer.Abstractions.Attributes; 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); _injector.OpenConsole(process); 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; } if (!handshakeResponse.ClientRunning) { _logger.LogInformation("The client is not running, going to start it"); } else { if (handshakeResponse.InitializationResult is not null && !handshakeResponse.InitializationResult.Value.IsSuccess) { _logger.LogError("Received an error from the Inject assembly that failed on initialization."); _logger.LogResultError(handshakeResponse.InitializationResult); } } // should be run only if !handshakeResponse.ClientRunning // but will work correctly even if client is already running. var clientRunResult = await connection.Connection.ContractRunClient(new RunClientRequest()) .WaitForAsync(DefaultStates.ResponseObtained, ct: stoppingToken); if (!clientRunResult.IsDefined(out var clientRun)) { _logger.LogResultError(clientRunResult); _lifetime.StopApplication(); return; } if (clientRun.InitializationResult is null) { _logger.LogError("Huh, the client did not return a result?"); } if (!(clientRun.BindingManagerResult?.IsSuccess ?? true)) { _logger.LogError("Binding manager threw an error."); _logger.LogResultError(clientRun.BindingManagerResult); } if (!(clientRun.InitializationResult?.IsSuccess ?? true)) { _logger.LogResultError(clientRun.InitializationResult); } _logger.LogInformation($"Connected to NosTale"); var runResult = await connection.Connection.RunHandlerAsync(stoppingToken); if (!runResult.IsSuccess) { _logger.LogResultError(runResult); } _lifetime.StopApplication(); } }