~ruther/NosTale-Gfless

ref: 0433b5040dabe05c55139c75fbd63edac106b9ab NosTale-Gfless/NosTaleGfless/NostalePipeServer.cs -rw-r--r-- 4.2 KiB
0433b504 — František Boháček fix: close application for not parsed arguments 5 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
using System;
using System.Collections.Generic;
using System.Diagnostics.SymbolStore;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using NosTaleGfless.Pipes;

namespace NosTaleGfless
{
    public class NostalePipeServer
    {
        protected string _sessionToken;
        protected CancellationTokenSource _cancellationTokenSource;

        public NostalePipeServer(NostaleProcess process, string sessionToken)
        {
            _sessionToken = sessionToken;
            Process = process;
            _cancellationTokenSource = new CancellationTokenSource();

            Process.Process.Exited += OnNostaleExit;
        }

        public bool Successful { get; protected set; }

        public NostaleProcess Process { get; }

        public async Task Start()
        {
            byte[] buffer = new byte[1024];
            List<NamedPipeServerStream> servers = new List<NamedPipeServerStream>();
            servers.Add(CreateServer());
            
            while (!Successful)
            {
                NamedPipeServerStream serverStream = servers.Last();
                try
                {
                    await serverStream.WaitForConnectionAsync(_cancellationTokenSource.Token);
                }
                catch (OperationCanceledException)
                {
                    serverStream.Dispose();
                    break;
                }

                int read = await serverStream.ReadAsync(buffer, 0, 1024);
                ParamsMessage message = ParseMessage(buffer, read);

                string output = null;
                switch (message.Method)
                {
                    case "ClientLibrary.isClientRunning":
                        output = CreateResult<bool, ResultMessage<bool>>(message, true);
                        break;
                    case "ClientLibrary.initSession":
                        output = CreateResult<string, ResultMessage<string>>(message, message.Params.SessionId);
                        break;
                    case "ClientLibrary.queryAuthorizationCode":
                        output = CreateResult<string, ResultMessage<string>>(message, _sessionToken);
                        _sessionToken = null;
                        break;
                    case "ClientLibrary.queryGameAccountName":
                        output = CreateResult<string, ResultMessage<string>>(message, Process.Account.Name);
                        Process.Process.Exited -= OnNostaleExit;
                        Successful = true;
                        break;
                }

                if (!Successful)
                {
                    servers.Add(CreateServer());
                }

                if (output != null)
                {
                    byte[] data = Encoding.ASCII.GetBytes(output);
                    serverStream.Write(data, 0, data.Length);
                }
            }

            foreach (NamedPipeServerStream server in servers)
            {
                server.Dispose();
            }
        }

        protected NamedPipeServerStream CreateServer()
        {
            return new NamedPipeServerStream("GameforgeClientJSONRPC", PipeDirection.InOut, 254,
                PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
        }

        protected ParamsMessage ParseMessage(byte[] data, int count)
        {
            return JsonConvert.DeserializeObject<ParamsMessage>(Encoding.ASCII.GetString(data, 0, count));
        }

        protected string SerializeResult<T>(ResultMessage<T> result)
        {
            return JsonConvert.SerializeObject(result);
            ;
        }

        protected string CreateResult<T, U>(ParamsMessage receivedMessage, T result)
            where U : ResultMessage<T>, new()
        {
            return SerializeResult(new U
            {
                Id = receivedMessage.Id,
                Jsonrpc = receivedMessage.Jsonrpc,
                Result = result
            });
        }

        protected void OnNostaleExit(object sender, EventArgs args)
        {
            Process.Process.Exited -= OnNostaleExit;
            _cancellationTokenSource.Cancel();
        }
    }
}