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
        }
Exemple #2
0
 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}");
     }
 }
Exemple #4
0
        public override bool OnStart()
        {
            if (_server == null)
                _server = new FtpServer();

            _server.NewConnection += ServerNewConnection;
            _server.UserLogoutEvent += ServerLogoutEvent;
            _server.errorHandler += ErrorHandle;

            return base.OnStart();
        }
Exemple #5
0
        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();
        }
Exemple #8
0
        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);
            }
        }
Exemple #9
0
        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;
        }
Exemple #11
0
        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();
        }
Exemple #12
0
        /// <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");
            }
        }
Exemple #13
0
        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();
        }