forked from Earu/GTerm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLogListener.cs
149 lines (127 loc) · 4.68 KB
/
LogListener.cs
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
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.IO.Pipes;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
namespace GTerm
{
internal class LogEventArgs : EventArgs
{
internal LogEventArgs(int type, int lvl, string grp, Color col, string msg)
{
this.Type = type;
this.Level = lvl;
this.Group = grp;
this.Color = col;
this.Message = msg;
}
internal int Type { get; private set; }
internal int Level { get; private set; }
internal string Group { get; private set; }
internal Color Color { get; private set; }
internal string Message { get; private set; }
}
delegate void LogEventHandler(object sender, LogEventArgs args);
internal class LogListener
{
private const int BUFFER_SIZE = 8192;
private readonly byte[] Buffer = new byte[BUFFER_SIZE];
private readonly NamedPipeClientStream Pipe;
internal event EventHandler OnConnected;
internal event EventHandler OnDisconnected;
internal event ErrorEventHandler OnError;
internal event LogEventHandler OnLog;
internal LogListener()
{
this.Pipe = new NamedPipeClientStream(
".",
"garrysmod_console",
PipeAccessRights.Read | PipeAccessRights.Write,
PipeOptions.Asynchronous,
TokenImpersonationLevel.Anonymous,
HandleInheritability.None
);
}
internal bool IsConnected { get; private set; }
private void SetConnectionStatus(bool connected)
{
if (connected)
this.OnConnected?.Invoke(this, EventArgs.Empty);
else
this.OnDisconnected?.Invoke(this, EventArgs.Empty);
this.IsConnected = connected;
}
private string ReadString(BinaryReader reader)
{
List<byte> list = new List<byte>();
byte ch = 0;
while ((ch = reader.ReadByte()) != 0)
list.Add(ch);
return Encoding.UTF8.GetString(list.ToArray());
}
private async Task ProcessMessages()
{
while (true)
{
try
{
await this.Pipe.ConnectAsync();
this.Pipe.ReadMode = PipeTransmissionMode.Message;
this.SetConnectionStatus(true);
while (this.Pipe.IsConnected)
{
try
{
int read = await this.Pipe.ReadAsync(this.Buffer, 0, BUFFER_SIZE);
if (read == 0) continue;
using (BinaryReader reader = new BinaryReader(new MemoryStream(this.Buffer, 0, read)))
{
int type = reader.ReadInt32();
int level = reader.ReadInt32();
string group = this.ReadString(reader);
Color color = Color.FromArgb(
reader.ReadByte(),
reader.ReadByte(),
reader.ReadByte()
);
reader.ReadByte();
string fullMsg = this.ReadString(reader).Replace("<NEWLINE>", "\n");
this.OnLog?.Invoke(this, new LogEventArgs(type, level, group, color, fullMsg));
}
}
catch (Exception ex)
{
this.OnError?.Invoke(this, new ErrorEventArgs(ex));
}
}
this.SetConnectionStatus(false);
}
catch (TimeoutException) { } // ignore that
catch (Exception ex)
{
this.OnError?.Invoke(this, new ErrorEventArgs(ex));
}
}
}
internal void Start()
{
Task.Run(this.ProcessMessages);
}
internal async Task WriteMessage(string input)
{
if (!this.Pipe.IsConnected) return;
try
{
byte[] buffer = Encoding.UTF8.GetBytes(input);
await this.Pipe.WriteAsync(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}