BadScript 2
Loading...
Searching...
No Matches
BadNetworkConsoleHost.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Concurrent;
3using System.Collections.Generic;
4using System.Net.Sockets;
5using System.Threading;
6using System.Threading.Tasks;
7
9
11
16{
20 private readonly ConcurrentQueue<BadConsoleReadPacket> m_IncomingPackets =
21 new ConcurrentQueue<BadConsoleReadPacket>();
22
26 private readonly TcpListener? m_Listener;
27
31 private readonly object m_Lock = new object();
32
36 private readonly ConcurrentQueue<BadConsolePacket> m_OutgoingPackets = new ConcurrentQueue<BadConsolePacket>();
37
41 private ConsoleColor m_BackgroundColor = ConsoleColor.Black;
42
46 private TcpClient? m_Client;
47
51 private bool m_ExitRequested;
52
56 private ConsoleColor m_ForegroundColor = ConsoleColor.White;
57
61 private Thread? m_MessageThread;
62
67 public BadNetworkConsoleHost(TcpListener listner)
68 {
69 m_Listener = listner;
70 }
71
76 public BadNetworkConsoleHost(TcpClient client)
77 {
78 m_Client = client;
79 }
80
84 public bool IsConnected => m_Client != null;
85
89 public static int HeartBeatInterval { get; set; } = 3000;
90
94 public static int HeartBeatTimeOut { get; set; } = 5000;
95
99 public static int ReadSleepTimeout { get; set; } = 100;
100
101
105 public static int ReceiveSleepTimeout { get; set; } = 100;
106
110 public static int AcceptSleepTimeout { get; set; } = 100;
111
112#region IBadConsole Members
113
115 public void Write(string str)
116 {
117 m_OutgoingPackets.Enqueue(new BadConsoleWritePacket(false, str));
118 }
119
121 public void WriteLine(string str)
122 {
123 m_OutgoingPackets.Enqueue(new BadConsoleWritePacket(true, str));
124 }
125
127 public string ReadLine()
128 {
130
131 while (!m_IncomingPackets.TryDequeue(out ret))
132 {
133 Thread.Sleep(ReadSleepTimeout);
134 }
135
136 return ret.Message;
137 }
138
140 public Task<string> ReadLineAsync()
141 {
142 return Task.Run(ReadLine);
143 }
144
146 public void Clear()
147 {
149 }
150
152 public ConsoleColor ForegroundColor
153 {
154 get => m_ForegroundColor;
155 set
156 {
157 m_ForegroundColor = value;
158 m_OutgoingPackets.Enqueue(new BadConsoleColorChangePacket(false, value));
159 }
160 }
161
163 public ConsoleColor BackgroundColor
164 {
165 get => m_BackgroundColor;
166 set
167 {
168 m_BackgroundColor = value;
169 m_OutgoingPackets.Enqueue(new BadConsoleColorChangePacket(true, value));
170 }
171 }
172
173#endregion
174
179 public void Start()
180 {
181 if (m_MessageThread != null)
182 {
183 throw new BadNetworkConsoleException("Message Thread already running");
184 }
185
186 lock (m_Lock)
187 {
188 m_ExitRequested = false;
189 }
190
191 m_MessageThread = new Thread(MessageThread);
192 m_MessageThread.Start();
193 }
194
199 public void Stop()
200 {
201 if (m_MessageThread == null)
202 {
203 throw new BadNetworkConsoleException("Message Thread is not running");
204 }
205
206 lock (m_Lock)
207 {
208 m_ExitRequested = true;
209 }
210 }
211
212
216 public void Disconnect()
217 {
219 }
220
225 private void MessageThread()
226 {
227 while (!m_ExitRequested)
228 {
229 if (m_Listener != null && m_Client is not { Connected: true })
230 {
231 m_Listener.Start();
232 BadConsole.WriteLine($"[Console Host] Waiting for Connection on {m_Listener.LocalEndpoint}");
233 bool accepted = false;
234
235 m_Listener.BeginAcceptTcpClient(ar =>
236 {
237 m_Client = m_Listener.EndAcceptTcpClient(ar);
238 accepted = true;
239 },
240 null
241 );
242
243 while (!accepted && !m_ExitRequested)
244 {
245 Thread.Sleep(AcceptSleepTimeout);
246 }
247
248 m_Listener.Stop();
249 }
250
252 DateTime lastHeartBeat = DateTime.Now;
253
254 while (!m_ExitRequested && m_Client != null && m_Client!.Connected)
255 {
256 bool done = false;
257
258 if (m_Client.Available != 0)
259 {
260 done = true;
261 lastHeartBeat = DateTime.Now;
262 byte[] len = new byte[sizeof(int)];
263 NetworkStream stream = m_Client.GetStream();
264 int read = stream.Read(len, 0, len.Length);
265
266 if (read != len.Length)
267 {
268 throw new BadNetworkConsoleException("Invalid Packet Size");
269 }
270
271 byte[] packet = new byte[BitConverter.ToInt32(len, 0)];
272 read = stream.Read(packet, 0, packet.Length);
273
274 if (read != packet.Length)
275 {
276 throw new BadNetworkConsoleException("Invalid Packet");
277 }
278
280
281 if (packetObj is BadConsoleReadPacket rp)
282 {
283 m_IncomingPackets.Enqueue(rp);
284 }
285 else if (packetObj is BadConsoleHeartBeatPacket)
286 {
287 //Ignore Packet
288 }
289 else if (packetObj is BadConsoleDisconnectPacket)
290 {
291 m_Client.Dispose();
292 m_Client = null;
293
294 break;
295 }
296 else
297 {
298 throw new BadNetworkConsoleException("Invalid Packet Type");
299 }
300 }
301
302 if (m_Client != null && m_OutgoingPackets.Count != 0)
303 {
304 if (m_OutgoingPackets.TryDequeue(out BadConsolePacket packet))
305 {
306 done = true;
307 NetworkStream stream = m_Client.GetStream();
308 List<byte> packetData = new List<byte>();
309 byte[] packetBytes = packet.Serialize();
310 packetData.AddRange(BitConverter.GetBytes(packetBytes.Length));
311 packetData.AddRange(packetBytes);
312 stream.Write(packetData.ToArray(), 0, packetData.Count);
313 }
314 }
315
316 if (done)
317 {
318 continue;
319 }
320
321 if (lastHeartBeat + TimeSpan.FromMilliseconds(HeartBeatTimeOut) < DateTime.Now)
322 {
323 m_Client?.Dispose();
324 }
325
326 Thread.Sleep(ReceiveSleepTimeout);
327 }
328 }
329
330 if (m_Client != null && m_Client!.Connected)
331 {
332 NetworkStream stream = m_Client.GetStream();
333 List<byte> packetData = new List<byte>();
334 byte[] packetBytes = BadConsoleDisconnectPacket.Packet.Serialize();
335 packetData.AddRange(BitConverter.GetBytes(packetBytes.Length));
336 packetData.AddRange(packetBytes);
337 stream.Write(packetData.ToArray(), 0, packetData.Count);
338 m_Client.Dispose();
339 m_Client = null;
340 }
341
342 m_MessageThread = null;
343 }
344}
Wrapper class for the console abstraction.
Definition BadConsole.cs:12
static void WriteLine(string str)
Writes a string to the console and appends a newline.
Definition BadConsole.cs:78
Exception that is thrown when the remote console encounters an error.
static int ReadSleepTimeout
The Time Interval that the Read Thread will sleep if no data is available.
readonly ConcurrentQueue< BadConsolePacket > m_OutgoingPackets
The Outgoing Packet Queue.
static int HeartBeatInterval
The Interval in which the Host will send Heartbeat Packets to the Client.
BadNetworkConsoleHost(TcpListener listner)
Constructs a new Host from a TCP Listener.
readonly ConcurrentQueue< BadConsoleReadPacket > m_IncomingPackets
Queue of Incoming Packets.
static int HeartBeatTimeOut
The Timeout after which the Host will disconnect the Client if no Heartbeat Packet was received.
string ReadLine()
Reads a line from the console.The line that was read
Task< string > ReadLineAsync()
Reads a line from the console asynchronously.The line that was read
static int AcceptSleepTimeout
The Time Interval that the Accept Thread will sleep if no data is available.
static int ReceiveSleepTimeout
The Time Interval that the Write Thread will sleep if no data is available.
void WriteLine(string str)
Writes a string to the console and appends a newline.
BadNetworkConsoleHost(TcpClient client)
Constructs a new Host from a TCP Client.
static readonly BadConsoleClearPacket Packet
Static Instance of this Packet.
static readonly BadConsoleDisconnectPacket Packet
Static Instance of this Packet.
static BadConsolePacket Deserialize(byte[] data)
Deserializes a BadConsolePacket from the given data.
Interface that abstracts the console.
Contains the network packets for the remote console.
Contains the Implementation of the Remote Console Abstraction over TCP.