~ruther/NosSmooth.Comms

ref: b06241f4c3251cb4b2ddfb0bf29d5936f5906637 NosSmooth.Comms/src/Local/NosSmooth.Comms.Local/CommsInjector.cs -rw-r--r-- 6.3 KiB
b06241f4 — František Boháček feat: remove Character id and name from HandshakeResponse 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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
//
//  CommsInjector.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.DependencyInjection;
using NosSmooth.Comms.Core;
using NosSmooth.Comms.Core.NamedPipes;
using NosSmooth.Comms.Data;
using NosSmooth.Comms.Inject;
using NosSmooth.Injector;
using NosSmooth.LocalBinding;
using NosSmooth.LocalBinding.Options;
using Remora.Results;

namespace NosSmooth.Comms.Local;

/// <summary>
/// Injects communication (tcp or named pipes) into a nostale process.
/// </summary>
public class CommsInjector
{
    private readonly IServiceProvider _serviceProvider;
    private readonly NosInjector _injector;
    private readonly NostaleClientResolver _resolver;

    /// <summary>
    /// Initializes a new instance of the <see cref="CommsInjector"/> class.
    /// </summary>
    /// <param name="serviceProvider">The service provider.</param>
    /// <param name="injector">The injector.</param>
    /// <param name="resolver">The nostale client resolver.</param>
    public CommsInjector(IServiceProvider serviceProvider, NosInjector injector, NostaleClientResolver resolver)
    {
        _serviceProvider = serviceProvider;
        _injector = injector;
        _resolver = resolver;
    }

    /// <summary>
    /// Find processes that are NosTale and create a <see cref="NosBrowserManager"/> from them.
    /// </summary>
    /// <param name="filterNames">The names to filter when searching the processes. In case the array is empty, look for all processes.</param>
    /// <returns>A list of the NosTale processes.</returns>
    public static IEnumerable<Result<NosBrowserManager>> CreateNostaleProcesssesBrowsers(params string[] filterNames)
    {
        return FindNosTaleProcesses(filterNames)
            .Select
            (
                x =>
                {
                    var manager = new NosBrowserManager
                    (
                        x,
                        new PlayerManagerOptions(),
                        new SceneManagerOptions(),
                        new PetManagerOptions(),
                        new NetworkManagerOptions(),
                        new UnitManagerOptions()
                    );

                    var initResult = manager.Initialize();
                    if (!initResult.IsSuccess)
                    {
                        return Result<NosBrowserManager>.FromError(initResult.Error);
                    }

                    return manager;
                }
            );
    }

    /// <summary>
    /// Find processes that are NosTale.
    /// </summary>
    /// <param name="filterNames">The names to filter when searching the processes. In case the array is empty, look for all processes.</param>
    /// <returns>A list of the NosTale processes.</returns>
    public static IEnumerable<Process> FindNosTaleProcesses(params string[] filterNames)
    {
        var processes = Process.GetProcesses().AsEnumerable();

        if (filterNames.Length > 0)
        {
            processes = processes.Where(x => filterNames.Contains(x.ProcessName));
        }

        return processes
            .Where
            (
                x =>
                {
                    try
                    {
                        return NosBrowserManager.IsProcessNostaleProcess(x);
                    }
                    catch
                    {
                        return false;
                    }
                }
            );
    }

    /// <summary>
    /// Inject NosSmooth.Comms.Inject.dll into the process,
    /// enable tcp server and establish a connection to the server.
    /// </summary>
    /// <returns>The result containing information about the established connection.</returns>
    public Task<Result<Comms>>
        EstablishTcpConnectionAsync()
    {
        throw new NotImplementedException();
    }

    /// <summary>
    /// Inject NosSmooth.Comms.Inject.dll into the process,
    /// enable named pipes server and establish a connection to the server.
    /// </summary>
    /// <param name="process">The process to establish named pipes with.</param>
    /// <param name="stopToken">The token used for stopping the connection.</param>
    /// <param name="ct">The cancellation token used for cancelling the operation.</param>
    /// <returns>The result containing information about the established connection.</returns>
    public async Task<Result<Comms>> EstablishNamedPipesConnectionAsync
        (Process process, CancellationToken stopToken, CancellationToken ct)
    {
        var injectResult = Inject(process, nameof(DllMain.EnableNamedPipes));
        if (!injectResult.IsSuccess)
        {
            return Result<Comms>.FromError(injectResult);
        }

        var namedPipeClient = new NamedPipeClient($"NosSmooth_{process.Id}");

        var connectionResult = await namedPipeClient.ConnectAsync(ct);
        if (!connectionResult.IsSuccess)
        {
            return Result<Comms>.FromError(connectionResult);
        }

        var handler = ActivatorUtilities.CreateInstance<ConnectionHandler>
            (_serviceProvider, (IConnection)namedPipeClient);
        handler.StartHandler(stopToken);

        var nostaleClient = _resolver.Resolve(handler);
        return new Comms(process, handler, nostaleClient);
    }

    /// <summary>
    /// Open a console in the target process.
    /// </summary>
    /// <remarks>
    /// Log of inject will be printed to the console.
    /// </remarks>
    /// <param name="process">The process.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    public Result OpenConsole(Process process)
    {
        return Inject(process, nameof(DllMain.OpenConsole));
    }

    /// <summary>
    /// Close a console in the target process.
    /// </summary>
    /// <param name="process">The process.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    public Result CloseConsole(Process process)
    {
        return Inject(process, nameof(DllMain.CloseConsole));
    }

    private Result Inject(Process process, string method)
    {
        return _injector.Inject
        (
            process,
            Path.GetFullPath("NosSmooth.Comms.Inject.dll"),
            "NosSmooth.Comms.Inject.DllMain, NosSmooth.Comms.Inject",
            method
        );
    }
}
Do not follow this link