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 { private readonly BlockingQueue toClientQueue = new BlockingQueue (); private readonly Telnet telnet; private readonly Thread receiveThread = null; private readonly Thread sendThread = null; private bool authenticated = false; private readonly bool authEnabled; private readonly TcpClient client; private readonly EndPoint endpoint; private readonly int endpointAddressHash; private bool closed = false; public bool IsClosed { get { return closed; } } public bool IsAuthenticated { get { return !authEnabled || authenticated; } } public int EndPointHash { get { return endpointAddressHash; } } public TelnetConnection (Telnet owner, TcpClient client, bool authEnabled) { this.telnet = owner; this.authEnabled = authEnabled; this.client = client; this.endpoint = client.Client.RemoteEndPoint; if (endpoint is IPEndPoint) { endpointAddressHash = ((IPEndPoint)endpoint).Address.GetHashCode (); } else { endpointAddressHash = endpoint.GetHashCode (); Log.Out ("EndPoint is not an IPEndPoint but: " + endpoint.GetType ().ToString ()); } Log.Out ("Telnet connection from: " + endpoint); receiveThread = ThreadMaster.Create ("TelnetClientReceive_" + endpoint.ToString (), new ThreadStart (ReceiveThread)); receiveThread.Start (); sendThread = ThreadMaster.Create ("TelnetClientSend" + endpoint.ToString (), new ThreadStart (SendThread)); sendThread.Start (); if (authEnabled) { toClientQueue.Enqueue ("Please enter password:"); } else { LoginMessage (); } } private void LoginMessage () { toClientQueue.Enqueue ("*** Connected with 7DTD server."); toClientQueue.Enqueue ("*** Dedicated server only build"); toClientQueue.Enqueue ("*** Allocs server fixes loaded"); toClientQueue.Enqueue (string.Empty); toClientQueue.Enqueue ("Server IP: " + ((GamePrefs.GetString (EnumGamePrefs.ServerIP) != null && GamePrefs.GetString (EnumGamePrefs.ServerIP).Length != 0) ? GamePrefs.GetString (EnumGamePrefs.ServerIP) : "Any") ); toClientQueue.Enqueue ("Server port: " + GamePrefs.GetInt (EnumGamePrefs.ServerPort)); toClientQueue.Enqueue ("Max players: " + GamePrefs.GetInt (EnumGamePrefs.ServerMaxPlayerCount)); toClientQueue.Enqueue ("Game mode: " + GamePrefs.GetString (EnumGamePrefs.GameMode)); toClientQueue.Enqueue ("World: " + GamePrefs.GetString (EnumGamePrefs.GameWorld)); toClientQueue.Enqueue ("Game name: " + GamePrefs.GetString (EnumGamePrefs.GameName)); toClientQueue.Enqueue ("Difficulty: " + GamePrefs.GetInt (EnumGamePrefs.GameDifficulty)); toClientQueue.Enqueue (string.Empty); toClientQueue.Enqueue ("Press 'help' to get a list of all commands. Press 'exit' to end session."); toClientQueue.Enqueue (string.Empty); } private void ReceiveThread () { try { StreamReader reader = new StreamReader (client.GetStream ()); while (!closed) { string line = reader.ReadLine (); if (line != null && (line = line.Trim ()).Length > 0) { if (!IsAuthenticated) { if (line.Equals (GamePrefs.GetString (EnumGamePrefs.TelnetPassword))) { authenticated = true; toClientQueue.Enqueue ("Logon successful."); toClientQueue.Enqueue (string.Empty); toClientQueue.Enqueue (string.Empty); toClientQueue.Enqueue (string.Empty); LoginMessage (); } else { if (telnet.RegisterFailedLogin (this)) { toClientQueue.Enqueue ("Password incorrect, please enter password:"); } else { toClientQueue.Enqueue ("Too many failed login attempts!"); Thread.Sleep (100); Close (true); break; } } } else { if (line.ToLower ().Equals ("exit")) { break; } Log.Out ("Telnet executed \"" + line + "\" from: " + endpoint); ConsoleOutputSeparator.QueueNetCommand (line, this); } } } } catch (Exception) { } if (!closed) Close (); ThreadMaster.Remove (Thread.CurrentThread.Name); } private void SendThread () { try { while (!closed && client.GetStream ().CanWrite) { string line = toClientQueue.Dequeue (); if (!closed && client.GetStream ().CanWrite) { if (line == null) { client.GetStream ().WriteByte (0); } else { byte[] utfData = Encoding.UTF8.GetBytes (line); client.GetStream ().Write (utfData, 0, utfData.Length); client.GetStream ().WriteByte (13); client.GetStream ().WriteByte (10); } } } } catch (Exception) { } if (!closed) Close (); ThreadMaster.Remove (Thread.CurrentThread.Name); } public void Close (bool kickedForLogins = false) { if (!closed) { closed = true; toClientQueue.Close (); client.GetStream ().Close (); client.Close (); telnet.ConnectionClosed (this); if (kickedForLogins) Log.Out ("Telnet connection closed for too many login attempts: " + endpoint); else Log.Out ("Telnet connection closed: " + endpoint); } } public void SendLine (string line) { if (!closed && IsAuthenticated) toClientQueue.Enqueue (line); else toClientQueue.Enqueue (null); } public void SendLog (string text, string trace, UnityEngine.LogType type) { throw new System.NotImplementedException (); } public string GetDescription () { return "Telnet from " + endpoint; } } }