private void ThreadMonitor() { while (m_theThread.IsAlive) { DateTime currentTime = DateTime.UtcNow; DateTime lastActivityCopy; TimeSpan timeSpan; lock (lastActiveLock) { lastActivityCopy = m_lastActiveTime; timeSpan = currentTime - m_lastActiveTime; } // has been idle for a long time if ((timeSpan.TotalSeconds > m_maxIdleSeconds) && !m_theCommands.DataSocketOpen) { FtpServer.LogWrite($"closing connection {RemoteEndPoint} because of idle timeout; " + $"last activity time: {lastActivityCopy}"); SocketHelpers.Send(m_theSocket, $"426 No operations for {m_maxIdleSeconds}+ seconds. Bye!", m_theCommands.Encoding); FtpServerMessageHandler.SendMessage(m_nId, "Connection closed for too long idle time."); Stop(); return; } Thread.Sleep(1000 * m_maxIdleSeconds); } return; // only monitor the work thread }
private void SendRejectMessage(TcpClient socket) { FtpServer.LogWrite(string.Format("{0} 421 Too many users now. Count {1}, Max {2}" , socket.Client.ToString(), m_apConnections.Count, m_maxClients) ); SocketHelpers.Send(socket, m_encoding.GetBytes("421 Too many users now\r\n")); }
private void MonitorSafelly() { try { ThreadMonitor(); } catch (Exception e) { FtpServer.LogWrite($"monitor thread for {RemoteEndPoint} failed: {e}"); } }
public override bool OnStart() { if (_server == null) _server = new FtpServer(); _server.NewConnection += ServerNewConnection; _server.UserLogoutEvent += ServerLogoutEvent; _server.errorHandler += ErrorHandle; return base.OnStart(); }
private void SendRejectMessage(TcpClient socket) { lock (m_apConnections) { FtpServer.LogWrite( $"{socket.Client.RemoteEndPoint} 421 Too many users now. Count {m_apConnections.Count}, Max {m_maxClients}" ); string clientsDump = string.Join("\r\n", m_apConnections.Select(c => $"\t{c.RemoteEndPoint}")); FtpServer.LogWrite($"connected clients:\r\n{clientsDump}"); SocketHelpers.Send(socket, m_encoding.GetBytes("421 Too many users now\r\n")); } }
private void RunSafelly() { try { ThreadRun(); } catch (Exception e) { FtpServer.LogWrite($"socket handler thread for {RemoteEndPoint} failed: {e}"); } finally { Closed?.Invoke(this); } }
public override bool OnStart() { // Set the maximum number of concurrent connections ServicePointManager.DefaultConnectionLimit = 12; //DiagnosticMonitor.Start("DiagnosticsConnectionString"); // For information on handling configuration changes // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357. RoleEnvironment.Changing += RoleEnvironmentChanging; if (_server == null) _server = _server = new FtpServer(new AzureFileSystemFactory()); _server.NewConnection += ServerNewConnection; return base.OnStart(); }
private void InitialiseSocketHandler(TcpClient socket) { lock (m_apConnections) { var handler = new FtpSocketHandler(m_fileSystemClassFactory, m_nId); handler.Closed += handler_Closed; // get encoding for the socket connection handler.Start(socket, m_encoding); m_apConnections.Add(handler); FtpServer.LogWrite( $"Client accepted: {socket.Client.RemoteEndPoint} current count={m_apConnections.Count}"); Trace.WriteLine( $"Handler created for client {handler.RemoteEndPoint}. Current Count {m_apConnections.Count}", "Information"); NewConnection?.Invoke(m_nId); } }
static void Main(string[] args) { Func<string, string> cfg = key => System.Configuration.ConfigurationManager.AppSettings[key]; Func<string, IPEndPoint> endpoint = name => { string epr = cfg(name + "_ENDPOINT"); var host = epr.Substring(0, epr.IndexOf(":")); var port = epr.Substring(epr.IndexOf(":") + 1); return new IPEndPoint(IPAddress.Parse(host), port.ToInt()); }; Func<IPEndPoint> getLocalAddress = () => { string ftpHost = cfg("FtpServerHost"); if (ftpHost.ToLower() == "localhost") return new IPEndPoint(address: IPAddress.Loopback, port: endpoint("FTPPASV").Port); foreach (var ip in Dns.GetHostEntry(ftpHost).AddressList) { if (ip.AddressFamily == AddressFamily.InterNetwork) { Trace.TraceInformation(string.Format("localAddress == {0}", ip)); return new IPEndPoint(address: ip, port: endpoint("FTPPASV").Port); } } return null; }; Func<Func<string, string, bool>> CheckAccount = () => { var json = File.ReadAllText(cfg("userfile")); var users = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(json); return (u, p) => users.ContainsKey(u) && users[u] == p; }; var _server = new FtpServer( fileSystemClassFactory: new AzureFileSystemFactory( storageAccount: cfg("StorageAccount"), sendQueueNotificationsOnUpload: bool.Parse(cfg("QueueNotification")), checkAccount: CheckAccount()), ftpEndpoint: endpoint("FTP"), localPasvEndpoint: endpoint("FTPPASV"), externallyVisiblePasvEndpoint: getLocalAddress(), maxClients: cfg("MaxClients").ToInt(), maxIdleTime: TimeSpan.FromSeconds(cfg("MaxIdleSeconds").ToInt()), connectionEncoding: cfg("ConnectionEncoding")); // var users = new Dictionary<string, string>(); //var _server = new FtpServer(fileSystemClassFactory: new AzureFileSystemFactory( // storageAccount: "UseDevelopmentStorage=true", // sendQueueNotificationsOnUpload: false, // checkAccount: (u, p) => users.ContainsKey(u) && users[u] == p), // ftpEndpoint: new IPEndPoint(IPAddress.Loopback, 21), // pasvEndpoint: new IPEndPoint(IPAddress.Loopback, 59860), // localAddress: IPAddress.Loopback, // maxClients: 5, // maxIdleTime: TimeSpan.FromMinutes(5), // connectionEncoding: "UTF8"); //users.Add("user", "pass"); //users.Add("$root", "testroot"); _server.NewConnection += (nId) => Console.WriteLine("Connection {0} accepted", nId); while (true) { if (!_server.Started) { _server.Start(); Console.WriteLine("Server starting."); } else { Thread.Sleep(TimeSpan.FromSeconds(10)); Console.WriteLine("Server running."); } } }
public void Process(byte[] abData) { string sMessage = this.Encoding.GetString(abData); // 2015-11-26 cljung : BUG .IndexOf returns -1 if search item isn't found. Substring throws exception with -1 int pos = sMessage.IndexOf('\r'); if (pos >= 0) { sMessage = sMessage.Substring(0, pos); } FtpServerMessageHandler.SendMessage(Id, sMessage); string sCommand; string sValue; int nSpaceIndex = sMessage.IndexOf(' '); if (nSpaceIndex < 0) { sCommand = sMessage.ToUpper(); sValue = ""; } else { sCommand = sMessage.Substring(0, nSpaceIndex).ToUpper(); sValue = sMessage.Substring(sCommand.Length + 1); } // check whether the client has logged in if (!isLogged) { if (!((sCommand == "USER") || (sCommand == "PASS") || (sCommand == "HELP") || (sCommand == "FEAT") || (sCommand == "QUIT"))) { SocketHelpers.Send(Socket, "530 Not logged in\r\n", this.Encoding); return; } } // check if data connection will be used if ((sCommand == "APPE") || (sCommand == "MLSD") || (sCommand == "LIST") || (sCommand == "RETR") || (sCommand == "STOR")) { m_useDataSocket = true; } var handler = m_theCommandHashTable[sCommand] as FtpCommandHandler; if (handler == null) { FtpServerMessageHandler.SendMessage(Id, $"\"{sCommand}\" : Unknown command"); FtpServer.LogWrite($"{Socket.Client.RemoteEndPoint.ToString()} Unknown/unsupported command: {sCommand}"); SocketHelpers.Send(Socket, "550 Unknown command\r\n", this.Encoding); } else { handler.Process(sValue); } // reset m_useDataSocket = false; }
public override bool OnStart() { // Set the maximum number of concurrent connections, no use? //ServicePointManager.DefaultConnectionLimit = 12; RoleEnvironment.Changing += RoleEnvironmentChanging; Func<string, string> cfg = RoleEnvironment.GetConfigurationSettingValue; Func<string, RoleInstanceEndpoint> endpoint = name => { return RoleEnvironment.CurrentRoleInstance.InstanceEndpoints[name]; }; //Func<IPEndPoint> getLocalAddressFromConfig = () => //{ // string ftpHost = cfg("FtpServerHost"); // var port = endpoint("FTPPASV").PublicIPEndpoint.Port; // // if (ftpHost.ToLower() == "localhost") // return new IPEndPoint(IPAddress.Loopback, port); // // foreach (var ip in Dns.GetHostEntry(ftpHost).AddressList) // { // if (ip.AddressFamily == AddressFamily.InterNetwork) // { // Trace.TraceInformation(string.Format("localAddress == {0}", ip)); // return new IPEndPoint(ip, port); // } // } // // return null; //}; Func<IPEndPoint> getExternalPASVFromWhatIsMyIp = () => { var externalAddress = ExternalIPFetcher.GetAddressAsync().Result.IPAddress; var externalPort = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["FTPPASV"].PublicIPEndpoint.Port; return new IPEndPoint(externalAddress, externalPort); }; var sb = new StringBuilder(); sb.AppendFormat("StorageAccount = {0}\r\n", cfg("StorageAccount")); sb.AppendFormat("localPasvEndpoint = {0}\r\n", endpoint("FTPPASV").IPEndpoint); sb.AppendFormat("externallyVisiblePasvEndpoint = {0}\r\n", getExternalPASVFromWhatIsMyIp()); sb.AppendFormat("FTPPASV.IPEndpoint = {0}\r\n", RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["FTPPASV"].IPEndpoint); sb.AppendFormat("FTPPASV.PublicIPEndpoint = {0}\r\n", RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["FTPPASV"].PublicIPEndpoint); File.WriteAllText(string.Format(@"C:\{0}_log.txt", RoleEnvironment.CurrentRoleInstance.Id), sb.ToString()); if (_server == null) _server = new FtpServer( fileSystemClassFactory: new AzureFileSystemFactory( storageAccount: cfg("StorageAccount"), sendQueueNotificationsOnUpload: bool.Parse(cfg("QueueNotification")), accounts: AccountManager.ParseOldConfiguration(cfg("FtpAccount"))), ftpEndpoint: endpoint("FTP").IPEndpoint, localPasvEndpoint: endpoint("FTPPASV").IPEndpoint, externallyVisiblePasvEndpoint: getExternalPASVFromWhatIsMyIp(), // getLocalAddressFromConfig(), maxClients: cfg("MaxClients").ToInt(), maxIdleTime: TimeSpan.FromSeconds(cfg("MaxIdleSeconds").ToInt()), connectionEncoding: cfg("ConnectionEncoding")); _server.NewConnection += ServerNewConnection; return base.OnStart(); }
/// <summary> /// The main thread of the ftp server /// Listen and acception clients, create handler threads for each client /// </summary> private void ThreadRun() { FtpServerMessageHandler.Message += TraceMessage; // listen at the port by the "FTP" endpoint setting int port = int.Parse(ConfigurationManager.AppSettings["FTP"]); System.Net.IPAddress ipaddr = SocketHelpers.GetLocalAddress(); System.Net.IPEndPoint ipEndPoint = new System.Net.IPEndPoint(ipaddr.Address, port); FtpServer.m_ftpIpAddr = ipaddr.ToString(); m_socketListen = SocketHelpers.CreateTcpListener(ipEndPoint); if (m_socketListen != null) { string msg = string.Format("FTP Server started.Listening to: {0}", ipEndPoint); FtpServer.LogWrite(msg); Trace.TraceInformation(msg); m_socketListen.Start(); bool fContinue = true; while (fContinue) { TcpClient socket = null; try { socket = m_socketListen.AcceptTcpClient(); } catch (SocketException) { fContinue = false; } finally { if (socket == null) { fContinue = false; } else if (m_apConnections.Count >= m_maxClients) { Trace.WriteLine("Too many clients, won't handle this connection", "Warnning"); SendRejectMessage(socket); socket.Close(); } else { socket.NoDelay = false; m_nId++; FtpServerMessageHandler.SendMessage(m_nId, "New connection"); SendAcceptMessage(socket); // 2015-11-25 cljung : under stress testing, this happens. Don't know why yet, but let's keep it from crashing try { InitialiseSocketHandler(socket); } catch (System.ObjectDisposedException ode) { Trace.TraceError(string.Format("ObjectDisposedException initializing client socket:\r\n{0}", ode)); m_nId--; // can't fail try { socket.Close(); } catch { } } } } } } else { FtpServerMessageHandler.SendMessage(0, "Error in starting FTP server"); } }
public override bool OnStart() { ServicePointManager.DefaultConnectionLimit = 100; DiagnosticMonitorConfiguration diagConfig = DiagnosticMonitor.GetDefaultInitialConfiguration(); /* diagConfig.Directories.ScheduledTransferPeriod = TimeSpan.FromSeconds(15); diagConfig.Logs.ScheduledTransferPeriod = TimeSpan.FromSeconds(15); */ PerformanceCounterConfiguration pccCPU = new PerformanceCounterConfiguration(); pccCPU.CounterSpecifier = @"\Processor(_Total)\% Processor Time"; pccCPU.SampleRate = TimeSpan.FromSeconds(5); diagConfig.PerformanceCounters.DataSources.Add(pccCPU); PerformanceCounterConfiguration pccMemory = new PerformanceCounterConfiguration(); pccMemory.CounterSpecifier = @"\Memory\Available Mbytes"; pccMemory.SampleRate = TimeSpan.FromSeconds(5); diagConfig.PerformanceCounters.DataSources.Add(pccMemory); PerformanceCounterConfiguration pccTcpFail = new PerformanceCounterConfiguration(); pccTcpFail.CounterSpecifier = @"\TCPv4\Connection Failures"; pccTcpFail.SampleRate = TimeSpan.FromSeconds(5); diagConfig.PerformanceCounters.DataSources.Add(pccTcpFail); diagConfig.PerformanceCounters.ScheduledTransferPeriod = TimeSpan.FromSeconds(15); //diagConfig.WindowsEventLog.DataSources.Add("System!*"); DiagnosticMonitor.Start("DiagnosticsConnectionString", diagConfig); System.Diagnostics.Trace.TraceInformation("OnStart Complete"); /* String myRoleInstanceName = RoleEnvironment.CurrentRoleInstance.Id; System.Diagnostics.Trace.TraceInformation("TraceInformation:" + myRoleInstanceName); CrashDumps.EnableCollection(true); CrashDumps.EnableCollection(false); */ RoleEnvironment.Changing += RoleEnvironmentChanging; if (_server == null) _server = _server = new FtpServer(new AzureFileSystemFactory()); _server.NewConnection += ServerNewConnection; CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) => { configSetter(RoleEnvironment.GetConfigurationSettingValue(configName)); RoleEnvironment.Changed += (sender, arg) => { if (arg.Changes.OfType<RoleEnvironmentConfigurationSettingChange>() .Any((change) => (change.ConfigurationSettingName == configName))) { if (!configSetter(RoleEnvironment.GetConfigurationSettingValue(configName))) { RoleEnvironment.RequestRecycle(); } } }; }); return base.OnStart(); }