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
113 public void Write(string str)
114 {
115 m_OutgoingPackets.Enqueue(new BadConsoleWritePacket(false, str));
116 }
117
119 public void WriteLine(string str)
120 {
121 m_OutgoingPackets.Enqueue(new BadConsoleWritePacket(true, str));
122 }
123
125 public string ReadLine()
126 {
128
129 while (!m_IncomingPackets.TryDequeue(out ret))
130 {
131 Thread.Sleep(ReadSleepTimeout);
132 }
133
134 return ret.Message;
135 }
136
138 public Task<string> ReadLineAsync()
139 {
140 return Task.Run(ReadLine);
141 }
142
144 public void Clear()
145 {
147 }
148
150 public ConsoleColor ForegroundColor
151 {
152 get => m_ForegroundColor;
153 set
154 {
155 m_ForegroundColor = value;
156 m_OutgoingPackets.Enqueue(new BadConsoleColorChangePacket(false, value));
157 }
158 }
159
161 public ConsoleColor BackgroundColor
162 {
163 get => m_BackgroundColor;
164 set
165 {
166 m_BackgroundColor = value;
167 m_OutgoingPackets.Enqueue(new BadConsoleColorChangePacket(true, value));
168 }
169 }
170
175 public void Start()
176 {
177 if (m_MessageThread != null)
178 {
179 throw new BadNetworkConsoleException("Message Thread already running");
180 }
181
182 lock (m_Lock)
183 {
184 m_ExitRequested = false;
185 }
186
187 m_MessageThread = new Thread(MessageThread);
188 m_MessageThread.Start();
189 }
190
195 public void Stop()
196 {
197 if (m_MessageThread == null)
198 {
199 throw new BadNetworkConsoleException("Message Thread is not running");
200 }
201
202 lock (m_Lock)
203 {
204 m_ExitRequested = true;
205 }
206 }
207
208
212 public void Disconnect()
213 {
215 }
216
221 private void MessageThread()
222 {
223 while (!m_ExitRequested)
224 {
225 if (m_Listener != null && m_Client is not { Connected: true })
226 {
227 m_Listener.Start();
228 BadConsole.WriteLine($"[Console Host] Waiting for Connection on {m_Listener.LocalEndpoint}");
229 bool accepted = false;
230 m_Listener.BeginAcceptTcpClient(
231 ar =>
232 {
233 m_Client = m_Listener.EndAcceptTcpClient(ar);
234 accepted = true;
235 },
236 null
237 );
238
239 while (!accepted && !m_ExitRequested)
240 {
241 Thread.Sleep(AcceptSleepTimeout);
242 }
243
244 m_Listener.Stop();
245 }
246
248 DateTime lastHeartBeat = DateTime.Now;
249
250 while (!m_ExitRequested && m_Client != null && m_Client!.Connected)
251 {
252 bool done = false;
253
254 if (m_Client.Available != 0)
255 {
256 done = true;
257 lastHeartBeat = DateTime.Now;
258 byte[] len = new byte[sizeof(int)];
259 NetworkStream stream = m_Client.GetStream();
260 int read = stream.Read(len, 0, len.Length);
261
262 if (read != len.Length)
263 {
264 throw new BadNetworkConsoleException("Invalid Packet Size");
265 }
266
267 byte[] packet = new byte[BitConverter.ToInt32(len, 0)];
268 read = stream.Read(packet, 0, packet.Length);
269
270 if (read != packet.Length)
271 {
272 throw new BadNetworkConsoleException("Invalid Packet");
273 }
274
276
277 if (packetObj is BadConsoleReadPacket rp)
278 {
279 m_IncomingPackets.Enqueue(rp);
280 }
281 else if (packetObj is BadConsoleHeartBeatPacket)
282 {
283 //Ignore Packet
284 }
285 else if (packetObj is BadConsoleDisconnectPacket)
286 {
287 m_Client.Dispose();
288 m_Client = null;
289
290 break;
291 }
292 else
293 {
294 throw new BadNetworkConsoleException("Invalid Packet Type");
295 }
296 }
297
298 if (m_Client != null && m_OutgoingPackets.Count != 0)
299 {
300 if (m_OutgoingPackets.TryDequeue(out BadConsolePacket packet))
301 {
302 done = true;
303 NetworkStream stream = m_Client.GetStream();
304 List<byte> packetData = new List<byte>();
305 byte[] packetBytes = packet.Serialize();
306 packetData.AddRange(BitConverter.GetBytes(packetBytes.Length));
307 packetData.AddRange(packetBytes);
308 stream.Write(packetData.ToArray(), 0, packetData.Count);
309 }
310 }
311
312 if (done)
313 {
314 continue;
315 }
316
317 if (lastHeartBeat + TimeSpan.FromMilliseconds(HeartBeatTimeOut) < DateTime.Now)
318 {
319 m_Client?.Dispose();
320 }
321
322 Thread.Sleep(ReceiveSleepTimeout);
323 }
324 }
325
326 if (m_Client != null && m_Client!.Connected)
327 {
328 NetworkStream stream = m_Client.GetStream();
329 List<byte> packetData = new List<byte>();
330 byte[] packetBytes = BadConsoleDisconnectPacket.Packet.Serialize();
331 packetData.AddRange(BitConverter.GetBytes(packetBytes.Length));
332 packetData.AddRange(packetBytes);
333 stream.Write(packetData.ToArray(), 0, packetData.Count);
334 m_Client.Dispose();
335 m_Client = null;
336 }
337
338 m_MessageThread = null;
339 }
340}
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:76
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.