예제 #1
0
        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
        }
예제 #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"));
 }
예제 #3
0
 private void MonitorSafelly()
 {
     try
     {
         ThreadMonitor();
     }
     catch (Exception e)
     {
         FtpServer.LogWrite($"monitor thread for {RemoteEndPoint} failed: {e}");
     }
 }
예제 #4
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"));
            }
        }
예제 #5
0
 private void RunSafelly()
 {
     try
     {
         ThreadRun();
     }
     catch (Exception e)
     {
         FtpServer.LogWrite($"socket handler thread for {RemoteEndPoint} failed: {e}");
     }
     finally
     {
         Closed?.Invoke(this);
     }
 }
예제 #6
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);
            }
        }
        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;
        }
예제 #8
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");
            }
        }