using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; namespace AllocsFixes.NetConnections.Servers.Telnet { public class TelnetConnection : IConnection { BlockingQueue toClientQueue = new BlockingQueue (); private Thread receiveThread = null; private Thread sendThread = null; private bool authenticated = false; private bool authEnabled; private TcpClient client; private NetworkStream stream; private EndPoint endpoint; public TelnetConnection (TcpClient client, bool authEnabled) { this.authEnabled = authEnabled; this.client = client; this.stream = client.GetStream (); this.endpoint = client.Client.RemoteEndPoint; Log.Out ("Telnet connection from: " + endpoint); receiveThread = ThreadMaster.Create ("TelnetClientReceive", new ThreadStart (ReceiveThread)); receiveThread.Start (); sendThread = ThreadMaster.Create ("TelnetClientSend", new ThreadStart (SendThread)); sendThread.Start (); if (authEnabled) { WriteLine ("Please enter password:"); } else { LoginMessage (); } } private void LoginMessage () { WriteLine ("*** Connected with 7DTD server."); WriteLine ("*** Dedicated server only build"); WriteLine ("*** Allocs server fixes loaded"); WriteLine (string.Empty); WriteLine ("Server IP: " + ((GamePrefs.GetString (EnumGamePrefs.ServerIP) != null && GamePrefs.GetString (EnumGamePrefs.ServerIP).Length != 0) ? GamePrefs.GetString (EnumGamePrefs.ServerIP) : "Any") ); WriteLine ("Server port: " + GamePrefs.GetInt (EnumGamePrefs.ServerPort)); WriteLine ("Max players: " + GamePrefs.GetInt (EnumGamePrefs.ServerMaxPlayerCount)); WriteLine ("Game mode: " + GamePrefs.GetString (EnumGamePrefs.GameMode)); WriteLine ("World: " + GamePrefs.GetString (EnumGamePrefs.GameWorld)); WriteLine ("Game name: " + GamePrefs.GetString (EnumGamePrefs.GameName)); WriteLine ("Difficulty: " + GamePrefs.GetInt (EnumGamePrefs.GameDifficulty)); WriteLine (string.Empty); WriteLine ("Press 'help' to get a list of all commands. Press 'exit' to end session."); WriteLine (string.Empty); } private void ReceiveThread () { try { StreamReader reader = new StreamReader (stream); try { while (!IsClosed()) { string line = reader.ReadLine (); if (line != null) { line = line.Trim (); if (!IsAuthenticated ()) { if (line.Equals (GamePrefs.GetString (EnumGamePrefs.TelnetPassword))) { authenticated = true; WriteLine ("Logon successful."); WriteLine (string.Empty); WriteLine (string.Empty); WriteLine (string.Empty); LoginMessage (); } else { WriteLine ("Password incorrect, please enter password:"); } } else { if (line.ToLower ().Equals ("exit")) { Log.Out ("Telnet connection closed by client: " + endpoint); Close (); break; } Log.Out ("Telnet executed \"" + line + "\" from: " + endpoint); ConsoleOutputSeparator.QueueNetCommand (line, this); } } } } catch (ObjectDisposedException) { } catch (IOException) { } catch (ThreadInterruptedException) { } ThreadMaster.Remove (Thread.CurrentThread.Name); } catch (Exception ex) { Log.Out ("Error in TelnetClientReceive: " + ex); } } private void SendThread () { try { while (!IsClosed() && stream.CanWrite) { try { string line = toClientQueue.Dequeue (); if (!IsClosed () && stream.CanWrite) { byte[] utfData = Encoding.UTF8.GetBytes (line); stream.Write (utfData, 0, utfData.Length); stream.WriteByte (13); stream.WriteByte (10); } } catch (IOException) { } catch (ThreadInterruptedException) { } catch (Exception e) { Log.Out ("Error writing to client: " + e); } } ThreadMaster.Remove (Thread.CurrentThread.Name); } catch (Exception ex) { Log.Out ("Error in TelnetClientSend: " + ex); } } public void WriteLine (string s) { toClientQueue.Enqueue (s); } public void Close () { if (receiveThread != null) { receiveThread.Interrupt (); } if (sendThread != null) { sendThread.Interrupt (); } if (client != null) client.Close (); client = null; } public bool IsClosed () { if (client != null && !client.Connected) { Log.Out ("Telnet connection interrupted: " + endpoint); Close (); } return (client == null) || (!client.Connected); } public bool IsAuthenticated () { return !authEnabled || authenticated; } } }