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, 4 days ago) by figdor32
File size: 8806 byte(s)
Log Message:
Initial check-in

File Contents

# User Rev Content
1 figdor32 2 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     }