ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/Qzhteln/trunk/TELTest/ConnectionHandler.cs
Revision: 2
Committed: Wed Feb 11 13:07:01 2026 UTC (8 weeks, 3 days ago) by figdor32
File size: 8806 byte(s)
Log Message:
Initial check-in

File Contents

# Content
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Net.Sockets;
5 using System.Text;
6 using System.Threading;
7 using System.Threading.Tasks;
8
9 namespace TELTest {
10 public abstract class ConnectionHandler {
11 public static List<ConnectionHandler> AllHandlers { get; } = new List<ConnectionHandler>();
12 public ConnectionHandler() {
13 ID = AllHandlers.Count;
14 AllHandlers.Add(this);
15 }
16 public int ID { get; protected set; }
17 public abstract Task HandleMe(NetworkStream stream);
18 public async Task Handle(NetworkStream stream) {
19 await Task.Delay(500); // PBX flashbacks
20 await WriteASCII(stream, "Processing.\r\n");
21 await Task.Delay(100);
22 Flush(stream);
23 //await ReadTimeout(stream, 100); // Catch loose buffered chars
24 await TryClear(stream);
25 await WriteASCII(stream, "Hello!\r\n");
26 await WriteASCII(stream, (ID + 1) + " concurrent connections right now.\r\n");
27 await WriteASCII(stream, $"Server time is {DateTime.Now}\r\n");
28
29 await HandleMe(stream);
30 await WriteASCII(stream, "\r\n\r\nBye!\r\n");
31 AllHandlers.Remove(this);
32 }
33 public void Flush(NetworkStream stream) {
34 while (stream.DataAvailable) stream.ReadByte();
35 }
36 public int ReadOneIfAvailable(NetworkStream stream) {
37 if (!stream.DataAvailable) return -1;
38 return stream.ReadByte();
39 }
40 public async Task TryClear(NetworkStream stream) {
41 await WriteASCII(stream, "\x1b[2J\x1b[H");
42 }
43 public async Task<char> Choice(NetworkStream stream, char[] choice, string caption = null,
44 string prompt = null, char? def = null, bool echo = true, bool noNewLine = false,
45 bool caseSensitive = false, CancellationToken? token = null) {
46 if (choice.Length <= 0) throw new ArgumentOutOfRangeException(nameof(choice));
47
48 if (prompt == null) {
49 StringBuilder sb = new StringBuilder();
50 sb.Append('[');
51 for (int i = 0; i < choice.Length; i++) {
52 var item = choice[i];
53 string cs = (item + (i == choice.Length - 1 ? "" : "/"));
54 cs = caseSensitive ? cs : cs.ToUpper();
55 sb.Append(cs);
56 }
57 sb.Append(']');
58 if (def != null) {
59 string cs = " (" + def.Value + ")";
60 cs = caseSensitive ? cs : cs.ToUpper();
61 sb.Append(cs);
62 }
63 sb.Append(" > ");
64 prompt = sb.ToString();
65 }
66 char selection = '\0';
67 while (true) {
68 if (caption != null)
69 await WriteASCII(stream, "\r\n" + caption + "\r\n");
70
71
72 await WriteASCII(stream, prompt);
73 char c = await ReadChar(stream,echo);
74 if (!noNewLine) await WriteASCII(stream, "\r\n");
75
76 for (int i = 0; i < choice.Length; i++) {
77 if (caseSensitive) {
78 if (choice[i] == c) {
79 selection = c;
80 goto ChoiceDone;
81 }
82 } else {
83 if (Char.ToUpper(choice[i]) == Char.ToUpper(c)) {
84 selection = choice[i];
85 goto ChoiceDone;
86 }
87 }
88 }
89 if (def != null) {
90 if (c == '\r' || c == '\n') {
91 selection = def.Value;
92 //while (stream.DataAvailable) stream.ReadByte();
93 goto ChoiceDone;
94 }
95 }
96 Flush(stream);
97 }
98 ChoiceDone:;
99 Flush(stream);
100 return selection;
101 }
102 public async Task<string> Prompt(NetworkStream stream, string prompt, ReadConfiguration? config = null, Nullable<CancellationToken> token = null) {
103 await WriteASCII(stream, prompt);
104 if (config == null) config = ReadConfiguration.Default;
105 string ret = await Read(stream, config.Value, token);
106 await WriteASCII(stream, "\r\n");
107 return ret;
108 }
109 public async Task<string> Read(NetworkStream stream, char terminator = '\r', bool echo = true, Nullable<CancellationToken> token = null) {
110 ReadConfiguration rc = ReadConfiguration.Default;
111 rc.Terminator = terminator;
112 rc.Echo = echo;
113 return await Read(stream, rc, token);
114 }
115 public async Task<string> Read(NetworkStream stream, ReadConfiguration config, Nullable<CancellationToken> token = null) {
116 byte[] buf = new byte[512];
117 int i = 0;
118 int con = 0;
119 while (true) {
120 if (token == null)
121 await stream.ReadAsync(buf, i, 1);
122 else
123 await stream.ReadAsync(buf, i, 1, token.Value);
124 if (buf[i] == 0x7F) {
125 buf[i] = (byte)'\b';
126 await WriteASCII(stream, "\b");
127 }
128
129 if (buf[i] == (byte)config.Terminator) { i++; break; }
130
131
132 if (buf[i] == (byte)'\b') {
133 i--;
134 con--;
135 i = i < 0 ? 0 : i;
136
137
138 if (con >= 0) {
139 await WriteASCII(stream, " \b");
140 } else if (con < 0) {
141 await WriteASCII(stream, " ");
142 con++;
143 }
144 continue;
145 } else {
146 i++;
147
148 if (!config.Echo) {
149 await WriteASCII(stream, "\b \b");
150 } else {
151 con++;
152 }
153 }
154 char cb = (char)buf[i - 1];
155 if (config.Whitelist != null && config.Whitelist.IndexOf(cb) == -1 && (cb != '\b' && cb != '\n' && cb != '\r')) {
156 //Console.WriteLine("Forbidden char - \"" + (char)buf[i] + "\"");
157 await WriteASCII(stream, "\b \b");
158 i--;
159 con--;
160 continue;
161 }
162 if (config.Echo && config.EchoPasswordChars) {
163 await WriteASCII(stream, "\b" + config.PasswordChar);
164 }
165 if (config.MaxLength + 1 == i) {
166 i--;
167 con--;
168 await WriteASCII(stream, "\b \b");
169 }
170 //Console.WriteLine(buf[i > 0 ? i - 1 : 0].ToString("X") + ", " + i + " curs " + con);
171 }
172 string ret = System.Text.Encoding.ASCII.GetString(buf, 0, i - 1);
173 if (config.FlushAfterReading) Flush(stream);
174 return ret.Trim();
175 }
176 protected int Columns { get; set; } = 120;
177 public String PlayerName { get; set; }
178 public bool PlayerReady { get; set; }
179 public object SharedTempUserObject { get; set; }
180
181 public async Task<string> ReadTimeout(NetworkStream stream, int timeout, string def = null, char terminator = '\n') {
182 CancellationTokenSource cts = new CancellationTokenSource();
183
184 Task<string> ts = Read(stream, terminator, true, cts.Token);
185 await Task.WhenAny(ts, Task.Delay(timeout));
186 cts.Cancel();
187 cts.Dispose();
188 return ts.IsCompleted ? ts.Result : def;
189 }
190 public async Task<char> ReadChar(NetworkStream stream, bool echo = true) {
191 byte[] buf = new byte[512];
192 await stream.ReadAsync(buf, 0, 1);
193 if (!echo && buf[0] != 8) await WriteASCII(stream, "\b \b");
194 //string ret = System.Text.Encoding.ASCII.GetString(buf, 0, i - 1);
195 return (char)buf[0];
196 }
197 public async Task WriteBar(NetworkStream stream, char chr = '=') {
198 await WriteASCII(stream, new string(chr, Columns) + "\r\n");
199 }
200 public async Task WriteASCII(NetworkStream stream, string text) {
201 var bytes = Encoding.ASCII.GetBytes(text);
202 await stream.WriteAsync(bytes, 0, bytes.Length);
203 }
204 }
205 }