~ruther/NosSmooth.Comms

ref: ae864d55d0a530321f0f9e9d9a2df6e6195e3bed NosSmooth.Comms/src/Samples/ConsolePacketLogger/ClientService.cs -rw-r--r-- 4.9 KiB
ae864d55 — František Boháček feat: add RunClientRequest message with support of setting binding options 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//
//  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;

/// <inheritdoc />
public class ClientService : BackgroundService
{
    private readonly IPacketTypesRepository _packetTypesRepository;
    private readonly CommsInjector _injector;
    private readonly IHostApplicationLifetime _lifetime;
    private readonly ILogger<ClientService> _logger;
    private readonly PacketLoggerOptions _options;

    /// <summary>
    /// Initializes a new instance of the <see cref="ClientService"/> class.
    /// </summary>
    /// <param name="packetTypesRepository">The packet types repository.</param>
    /// <param name="injector">The injector.</param>
    /// <param name="lifetime">The lifetime.</param>
    /// <param name="logger">The logger.</param>
    /// <param name="options">The options.</param>
    public ClientService
    (
        IPacketTypesRepository packetTypesRepository,
        CommsInjector injector,
        IHostApplicationLifetime lifetime,
        ILogger<ClientService> logger,
        IOptions<PacketLoggerOptions> options
    )
    {
        _packetTypesRepository = packetTypesRepository;
        _injector = injector;
        _lifetime = lifetime;
        _logger = logger;
        _options = options.Value;
    }

    /// <inheritdoc />
    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();
    }
}
Do not follow this link