source: binary-improvements/7dtd-server-fixes/src/AllocsNetTelnetServer.cs @ 74

Last change on this file since 74 was 74, checked in by alloc, 6 years ago

7dtd server fixes

File size: 6.1 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Net;
5using System.Net.Sockets;
6using System.Reflection;
7using System.Threading;
8
9public class AllocsNetTelnetServer
10{
11        private class Connection
12        {
13                private bool authenticated = false;
14                private TcpClient client;
15                private NetworkStream stream;
16                private string lineBuffer = string.Empty;
17                private EndPoint endpoint;
18
19                public Connection (TcpClient client)
20                {
21                        this.client = client;
22                        this.stream = client.GetStream ();
23                        this.endpoint = client.Client.RemoteEndPoint;
24                }
25
26                public EndPoint GetEndPoint ()
27                {
28                        return endpoint;
29                }
30
31                private void WriteByte (byte v)
32                {
33                        if (!IsClosed () && stream.CanWrite) {
34                                stream.WriteByte (v);
35                        }
36                }
37
38                public void WriteLine (string s)
39                {
40                        if (!IsClosed () && stream.CanWrite) {
41                                for (int i = 0; i < s.Length; i++) {
42                                        WriteByte ((byte)s [i]);
43                                }
44                                WriteByte (10);
45                        }
46                }
47
48                public void Close ()
49                {
50                        if (client != null)
51                                client.Close ();
52                        client = null;
53                }
54
55                public bool IsClosed ()
56                {
57                        if (client != null && !client.Connected) {
58                                Log.Out ("Telnet connection interrupted: " + endpoint);
59                        }
60                        return (client == null) || (!client.Connected);
61                }
62
63                public bool IsAuthenticated ()
64                {
65                        return !authEnabled || authenticated;
66                }
67
68                public void SetAuthenticated ()
69                {
70                        authenticated = true;
71                }
72
73                public bool Read ()
74                {
75                        while (!IsClosed() && stream.CanRead && stream.DataAvailable) {
76                                int b = stream.ReadByte ();
77                                if (b == '\r' || b == '\n') {
78                                        if (lineBuffer.Length > 0)
79                                                return true;
80                                } else {
81                                        lineBuffer += (char)b;
82                                }
83                        }
84                        return false;
85                }
86
87                public string GetLine ()
88                {
89                        string res = lineBuffer;
90                        lineBuffer = string.Empty;
91                        return res;
92                }
93        }
94
95        private static cl004c console = null;
96        private static Thread telnetThread = null;
97        private static TcpListener listener = null;
98        private static bool closed = false;
99        private static bool authEnabled = false;
100        private static List<Connection> conns = new List<Connection> ();
101
102        public static void init (int port)
103        {
104                Log.Out ("[7dtd-server-fixes by Alloc] Version: " + Assembly.GetExecutingAssembly().GetName().Version);
105                authEnabled = GamePrefs.GetString (EnumGamePrefs.TelnetPassword).Length != 0;
106                if (authEnabled)
107                        listener = new TcpListener (IPAddress.Any, port);
108                else
109                        listener = new TcpListener (IPAddress.Loopback, port);
110                telnetThread = ThreadMaster.Create ("thread Allocs TelnetListenThread", new ThreadStart (telnetListenThread));
111                telnetThread.Start ();
112                Log.Out ("Started Allocs NetTelnetServer thread on " + port);
113        }
114
115        private static void telnetListenThread ()
116        {
117                try {
118                        Log.Out ("Started thread_Allocs_TelnetListenThread()");
119                        listener.Start ();
120                        while (!closed) {
121                                Thread.Sleep (10);
122                                if (listener.Pending ()) {
123                                        Connection c = new Connection (listener.AcceptTcpClient ());
124                                        conns.Add (c);
125                                        Log.Out ("Telnet connection from: " + c.GetEndPoint ());
126                                        if (authEnabled) {
127                                                c.WriteLine ("Please enter password:");
128                                        } else {
129                                                LoginMessage (c);
130                                        }
131                                }
132
133                                foreach (Connection c in conns) {
134                                        if (c.IsClosed ()) {
135                                                c.Close ();
136                                                conns.Remove (c);
137                                                break;
138                                        }
139                                        if (c.Read ()) {
140                                                string line = lineCorrecter (c.GetLine ());
141                                                if (!c.IsAuthenticated ()) {
142                                                        if (line.Equals (GamePrefs.GetString (EnumGamePrefs.TelnetPassword))) {
143                                                                c.SetAuthenticated ();
144                                                                c.WriteLine ("Logon successful.");
145                                                                c.WriteLine (string.Empty);
146                                                                c.WriteLine (string.Empty);
147                                                                c.WriteLine (string.Empty);
148                                                                LoginMessage (c);
149                                                        } else {
150                                                                c.WriteLine ("Password incorrect, please enter password:");
151                                                        }
152                                                } else {
153                                                        if (line.ToLower ().Equals ("exit")) {
154                                                                Log.Out ("Telnet connection closed by client: " + c.GetEndPoint ());
155                                                                c.Close ();
156                                                                conns.Remove (c);
157                                                                break;
158                                                        }
159
160                                                        Log.Out ("Telnet executed \"" + line + "\" from: " + c.GetEndPoint ());
161                                                        console.md000f (line);
162                                                }
163                                        }
164                                }
165                        }
166                        Log.Out ("Exited thread_Allocs_TelnetListenThread()");
167                        ThreadMaster.Remove (Thread.CurrentThread.Name);
168                } catch (Exception ex) {
169                        Log.Out ("Error in Allocs telnetListenThread: " + ex.Message);
170                        Log.Out ("Stack Trace: " + ex.StackTrace);
171                }
172        }
173
174        private static void LoginMessage (Connection c)
175        {
176                c.WriteLine ("*** Connected with 7DTD server.");
177                c.WriteLine ("*** Server version: Alpha 8.7 (b29) Compatibility Version: Alpha 8.7");
178                c.WriteLine (string.Empty);
179                c.WriteLine ("Server IP:   " + 
180                        ((GamePrefs.GetString (EnumGamePrefs.ServerIP) != null && GamePrefs.GetString (EnumGamePrefs.ServerIP).Length != 0) ? GamePrefs.GetString (EnumGamePrefs.ServerIP) : "Any")
181                );
182                c.WriteLine ("Server port: " + GamePrefs.GetInt (EnumGamePrefs.ServerPort));
183                c.WriteLine ("Max players: " + GamePrefs.GetInt (EnumGamePrefs.ServerMaxPlayerCount));
184                c.WriteLine ("Game mode:   " + GamePrefs.GetString (EnumGamePrefs.GameMode));
185                c.WriteLine ("World:       " + GamePrefs.GetString (EnumGamePrefs.GameWorld));
186                c.WriteLine ("Game name:   " + GamePrefs.GetString (EnumGamePrefs.GameName));
187                c.WriteLine ("Difficulty:  " + GamePrefs.GetInt (EnumGamePrefs.GameDifficulty));
188                c.WriteLine (string.Empty);
189                c.WriteLine ("Press 'help' to get a list of all commands. Press 'exit' to end session.");
190                c.WriteLine (string.Empty);
191        }
192
193        private static string lineCorrecter (string line)
194        {
195                string res = "";
196                for (int i = 0; i < line.Length; i++) {
197                        if (line [i] >= ' ' && line [i] != '\'' && line [i] <= '~') {
198                                res += line [i];
199                        }
200                }
201                return res.Trim ();
202        }
203
204        public static void Disconnect ()
205        {
206                closed = true;
207                if (listener != null) {
208                        listener.Stop ();
209                }
210                foreach (Connection c in conns) {
211                        c.Close ();
212                }
213                Thread.Sleep (100);
214        }
215
216        public static void SetConsole (cl004c console)
217        {
218                AllocsNetTelnetServer.console = console;
219        }
220
221        private static void RemoveClosedConnections ()
222        {
223                foreach (Connection c in conns) {
224                        if (c.IsClosed ()) {
225                                c.Close ();
226                        }
227                }
228        }
229
230        public static void WriteToClient (string line)
231        {
232                if (line == null) {
233                        return;
234                }
235                RemoveClosedConnections ();
236                foreach (Connection c in conns) {
237                        if (c.IsAuthenticated())
238                                c.WriteLine (line);
239                }
240        }
241}
Note: See TracBrowser for help on using the repository browser.