using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Threading; namespace AllocsFixes.NetConnections.Servers.Telnet { public class Telnet : IServer { private const int MAX_LOGIN_ATTEMPTS = 10; private const int BLOCK_TIME_SECONDS = 10; private class LoginAttempts { private int count = 0; private DateTime lastAttempt = new DateTime (0); public bool LogAttempt () { lastAttempt = DateTime.Now; count++; return count < MAX_LOGIN_ATTEMPTS; } public bool IsBanned () { if ((DateTime.Now - lastAttempt).TotalSeconds > BLOCK_TIME_SECONDS) count = 0; return count >= MAX_LOGIN_ATTEMPTS; } } private TcpListener listener = null; private bool authEnabled = false; private List connections = new List (); private Dictionary loginAttemptsPerIP = new Dictionary (); public Telnet () { try { if (!GamePrefs.GetBool (EnumGamePrefs.TelnetEnabled)) { return; } int port = GamePrefs.GetInt (EnumGamePrefs.TelnetPort); authEnabled = GamePrefs.GetString (EnumGamePrefs.TelnetPassword).Length != 0; if (authEnabled) listener = new TcpListener (IPAddress.Any, port); else listener = new TcpListener (IPAddress.Loopback, port); listener.Start (); listener.BeginAcceptTcpClient (new AsyncCallback (AcceptClient), null); NetTelnetServer.RegisterServer (this); Log.Out ("Started Telnet on " + port); } catch (Exception e) { Log.Out ("Error in Telnet.ctor: " + e); } } private void AcceptClient (IAsyncResult asyncResult) { if (listener.Server.IsBound) { TcpClient client = listener.EndAcceptTcpClient (asyncResult); EndPoint endpoint = client.Client.RemoteEndPoint; int addressHash = -1; if (endpoint is IPEndPoint) { addressHash = ((IPEndPoint)endpoint).Address.GetHashCode (); } else { addressHash = endpoint.GetHashCode (); Log.Out ("EndPoint is not an IPEndPoint but: " + endpoint.GetType ().ToString ()); } lock (loginAttemptsPerIP) { LoginAttempts la = null; if (loginAttemptsPerIP.ContainsKey (addressHash)) la = loginAttemptsPerIP [addressHash]; if (la == null) { la = new LoginAttempts (); loginAttemptsPerIP [addressHash] = la; } if (!la.IsBanned ()) { TelnetConnection con = new TelnetConnection (this, client, authEnabled); lock (connections) { connections.Add (con); } } else { client.Close (); Log.Out ("Telnet connection not accepted for too many login attempts: " + endpoint); } } listener.BeginAcceptTcpClient (new AsyncCallback (AcceptClient), null); } } public bool RegisterFailedLogin (TelnetConnection con) { lock (loginAttemptsPerIP) { LoginAttempts la = loginAttemptsPerIP [con.EndPointHash]; return la.LogAttempt (); } } public void ConnectionClosed (TelnetConnection con) { lock (connections) { connections.Remove (con); } } public void Disconnect () { try { if (listener != null) { listener.Stop (); listener = null; } List cur = new List (connections); foreach (TelnetConnection c in cur) { c.Close (); } } catch (Exception e) { Log.Out ("Error in Telnet.Disconnect: " + e); } } public void SendLine (string line) { if (line == null) { return; } lock (connections) { foreach (TelnetConnection c in connections) { c.SendLine (line); } } } public void SendLog (string text, string trace, UnityEngine.LogType type) { throw new System.NotImplementedException (); } } }