コード例 #1
0
 /// <summary>
 /// Close both active and passive data connection if opened
 /// </summary>
 private void CloseDataChannel()
 {
     Logging.Print("hit close data channel");
     if (m_DataStream != null)
     {
         m_DataStream.Close();
         m_DataStream = null;
     }
     if (m_ListenSocket != null)
     {
         m_ListenSocket.Close();
         m_ListenSocket = null;
     }
     if (m_DataSocket != null)
     {
         m_DataSocket.Close();
         m_DataSocket = null;
     }
     if (m_PassThreadW == true)
     {
         m_PassThreadW = false;
     }
     else if (m_ActThreadW == true)
     {
         m_ActThreadW = false;
     }
     m_DataReady = false;
 }
コード例 #2
0
        /// <summary>
        /// Data thread running in passive mode
        /// </summary>
        private void PassiveThread()
        {
            m_HostPort = 0;
            Logging.Print("Passive Mode Activate");

            if (m_IsDisposed)
            {
                return;
            }

            // clean up data socket
            if (m_DataSocket != null)
            {
                m_DataSocket.Close();
                m_DataSocket = null;
            }

            IPAddress  hostIp = IPAddress.Any;
            IPEndPoint ep     = new IPEndPoint(hostIp, m_HostPort);

            try
            {
                m_ListenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                m_ListenSocket.Bind(ep);
                m_ListenSocket.Listen(0);
                m_HostPort    = (m_ListenSocket.LocalEndPoint as IPEndPoint).Port;
                m_PassThreadW = true;
            }
            catch (SocketException se)
            {
                Logging.Print(se.Message);
            }
            finally
            {
                m_DataReadyEvent.Set();
            }
            try
            {
                m_DataSocket = m_ListenSocket.Accept();
                m_DataStream = new NetworkStream(m_DataSocket);
                lock (m_SyncRoot)
                {
                    m_DataReady = true;
                }
                m_DataChannelEstablished.Set();
            }
            catch (SocketException se)
            {
                Logging.Print("Data Socket Exception: " + se.ErrorCode.ToString());
            }
            finally
            {
                // do not need listen socket any longer
                Logging.Print("Passive Thread exit");
                m_ListenSocket.Close();
                m_ListenSocket = null;
            }
        }
コード例 #3
0
 // Methods
 internal FtpListenerSession(Socket control, IContextManager context)
 {
     m_CommandSocket = control;
     m_SendContext   = context;
     Logging.Print("New connection established from " + control.RemoteEndPoint);
     m_HostIp                 = (control.LocalEndPoint as IPEndPoint).Address;
     m_DataReadyEvent         = new AutoResetEvent(false);
     m_DataChannelEstablished = new ManualResetEvent(false);
     m_CommandThread          = new Thread(WorkerThread);
     m_CommandThread.Start();
 }
コード例 #4
0
        /// <summary>
        /// Work thread to handle new ftp sessions
        /// </summary>
        private void WorkerThread()
        {
            m_ListenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                m_ListenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            }
            catch {}

            IPAddress  hostIp = new IPAddress(new byte[] { 0, 0, 0, 0 }); //IPAddress.Any;
            IPEndPoint ep     = new IPEndPoint(hostIp, m_HostPort);

            m_ListenSocket.Bind(ep);
            m_ListenSocket.Listen(0);
            Socket aSocket = null;

            try
            {
                aSocket = m_ListenSocket.Accept();

                try
                {
                    aSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                }
                catch {}

                while (m_IsStarted)
                {
                    // remove dead connections
                    m_Sessions.CheckAlive();

                    // too many open connections
                    if (m_Sessions.Count >= m_Sessions.Capacity)
                    {
                        aSocket.Close();
                        Logging.Print("Too many open connections");
                    }
                    else
                    {
                        m_Sessions.AddSession(new FtpListenerSession(aSocket, this));
                        Logging.Print("number of active sessions: " + m_Sessions.Count);
                    }

                    aSocket = m_ListenSocket.Accept();
                }
            }
            catch (SocketException)
            { }
        }
コード例 #5
0
 // Methods
 /// <summary>
 /// Default constructor
 /// </summary>
 private FtpListenerManager()
 {
     Logging.Print(" *** MiniFTPServer ***");
     foreach (IPAddress item in System.Net.Dns.GetHostEntry("").AddressList)
     {
         m_HostIP = item;
         if (null != m_HostIP)
         {
             break;
         }
     }
     m_Sessions  = new SessionPool();
     m_Listeners = new ArrayList();
     Logging.Print("Running in domain " + AppDomain.CurrentDomain.FriendlyName);
 }
コード例 #6
0
        /// <summary>
        /// read from the command socket
        /// </summary>
        /// <returns></returns>
        private string ReadCommand()
        {
            int    idxEndLine    = -1;
            string receiveBuffer = "";
            int    timeCountDown = SessionTimeOut;
            int    len           = 0;

            byte[] buffer;
            while (len == 0 || idxEndLine < 0)
            {
                if (len == 0)
                {
                    Thread.Sleep(50);
                    timeCountDown -= 50;
                }
                else
                {
                    timeCountDown = SessionTimeOut;
                }
                if (timeCountDown <= 0)
                {
                    m_IsAlive = false;
                    break;
                }
                len            = m_CommandSocket.Available;
                buffer         = new byte[len];
                len            = m_CommandSocket.Receive(buffer, len, SocketFlags.None);
                receiveBuffer += new string(Encoding.UTF8.GetChars(buffer));
                idxEndLine     = receiveBuffer.IndexOf('\n');
            }
            if (timeCountDown <= 0)
            {
                return(null);
            }
            receiveBuffer = receiveBuffer.Substring(0, idxEndLine - 1);
            Logging.Print("Get: " + receiveBuffer + " :" + SessionId.ToString() + " in domain " + AppDomain.CurrentDomain.FriendlyName);
            return(receiveBuffer);
        }
コード例 #7
0
 /// <summary>
 /// Start the ftp server
 /// </summary>
 internal void Start()
 {
     if (!m_IsStarted)
     {
         // Start the socket
         Logging.Print(" Host IP: " + m_HostIP.ToString());
         m_Daemon    = new Thread(WorkerThread);
         m_IsStarted = true;
         m_Daemon.Start();
         if (m_DefaultListener != null)
         {
             if (!m_DefaultListener.IsListening)
             {
                 m_DefaultListener.Start();
             }
         }
         else
         {
             m_DefaultListener = new FtpDefaultListener();
             m_DefaultListener.Start();
         }
     }
 }
コード例 #8
0
        /// <summary>
        /// Data thread running in active mode
        /// </summary>
        private void ActiveThread()
        {
            Logging.Print("Active Mode Activate");

            if (m_IsDisposed)
            {
                return;
            }

            // clean up data socket
            if (m_DataSocket != null)
            {
                m_DataSocket.Close();
                m_DataSocket = null;
            }
            try
            {
                m_DataSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                m_DataSocket.Connect(new IPEndPoint(m_ClientIp, m_ClientPort));
                m_DataStream = new NetworkStream(m_DataSocket);
                lock (m_SyncRoot)
                {
                    m_DataReady = true;
                }
                m_DataChannelEstablished.Set();
            }
            catch (SocketException se)
            {
                Logging.Print("Data Socket Exception: " + se.ErrorCode.ToString());
            }
            finally
            {
                // do not need listen socket any longer
                Logging.Print("Active Thread exit");
            }
        }
コード例 #9
0
        private void Run()
        {
            for (; ;)
            {
                FtpListenerContext context = this.GetContext();

                if (context == null)
                {
                    // the listener has been closed
                    return;
                }
                try
                {
                    switch (context.Request.Method)
                    {
                    case WebRequestMethodsEx.Ftp.ChangeDirectory:
                    {
                        String fsPath = MapToFilesystem(context.Request.QueryString);

                        if (fsPath[fsPath.Length - 1] == Path.DirectorySeparatorChar)
                        {
                            fsPath = fsPath.Substring(0, fsPath.Length - 1);
                        }

                        context.Response.StatusCode = Directory.Exists(fsPath) ? FtpStatusCode.FileActionOK : FtpStatusCode.ActionNotTakenFileUnavailable;
                    }
                    break;

                    case WebRequestMethods.Ftp.ListDirectory:
                    case WebRequestMethods.Ftp.ListDirectoryDetails:
                    {
                        String fsPath = MapToFilesystem(context.Request.QueryString);

                        if (fsPath[fsPath.Length - 1] == Path.DirectorySeparatorChar)
                        {
                            fsPath = fsPath.Substring(0, fsPath.Length - 1);
                        }

                        if (WriteDirInfo(fsPath, context.Response.OutputStream))
                        {
                            context.Response.StatusCode = FtpStatusCode.ClosingData;
                        }
                        else
                        {
                            context.Response.StatusCode = FtpStatusCode.ActionNotTakenFileUnavailable;
                        }
                    }
                    break;

                    case WebRequestMethods.Ftp.MakeDirectory:
                    {
                        String fsPath = MapToFilesystem(context.Request.QueryString);

                        if (fsPath[fsPath.Length - 1] == Path.DirectorySeparatorChar)
                        {
                            fsPath = fsPath.Substring(0, fsPath.Length - 1);
                        }

                        DirectoryInfo dinfo = Directory.CreateDirectory(fsPath);
                        context.Response.StatusCode = (null != dinfo && dinfo.Exists) ? FtpStatusCode.PathnameCreated : FtpStatusCode.ActionNotTakenFileUnavailable;
                    }
                    break;

                    case WebRequestMethods.Ftp.RemoveDirectory:
                    {
                        DirectoryInfo info = new DirectoryInfo(MapToFilesystem(context.Request.QueryString));
                        if (info.Exists)
                        {
                            info.Delete();
                            context.Response.StatusCode = FtpStatusCode.FileActionOK;
                        }
                        else
                        {
                            context.Response.StatusCode = FtpStatusCode.ActionNotTakenFilenameNotAllowed;
                        }
                    }
                    break;


                    case WebRequestMethods.Ftp.DownloadFile:
                    {
                        FileInfo info = new FileInfo(MapToFilesystem(context.Request.QueryString));
                        if (info.Exists)
                        {
                            using (FileStream dataFile = new FileStream(MapToFilesystem(context.Request.QueryString), FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                            {
                                context.Response.OutputStream.Write(dataFile);
                            }
                            context.Response.StatusCode = FtpStatusCode.ClosingData;
                        }
                        else
                        {
                            context.Response.StatusCode = FtpStatusCode.ActionNotTakenFileUnavailable;
                        }
                    }
                    break;

                    case WebRequestMethods.Ftp.UploadFile:
                        if (!UploadsAllowed)
                        {
                            Logging.Print("Uploads forbidden by configuration: " + context.Request.QueryString);
                            context.Response.StatusCode = FtpStatusCode.FileActionAborted;
                        }
                        else
                        {
                            FileInfo info = new FileInfo(MapToFilesystem(context.Request.QueryString));

                            FtpResponseStream istream = context.Request.InputStream;

                            using (FileStream dataFile = new FileStream(MapToFilesystem(context.Request.QueryString), FileMode.Create, FileAccess.ReadWrite, FileShare.Read))
                            {
                                istream.ReadTo(dataFile);
                                dataFile.Close();
                            }

                            context.Response.StatusCode = FtpStatusCode.ClosingData;
                        }
                        break;

                    case WebRequestMethods.Ftp.GetFileSize:
                    {
                        FileInfo info = new FileInfo(MapToFilesystem(context.Request.QueryString));
                        if (info.Exists)
                        {
                            context.Response.OutputStream.Write(((int)info.Length).ToString());
                            context.Response.StatusCode = FtpStatusCode.FileStatus;
                        }
                        else
                        {
                            context.Response.StatusCode = FtpStatusCode.ActionNotTakenFileUnavailable;
                        }
                    }
                    break;

                    case WebRequestMethods.Ftp.DeleteFile:
                    {
                        FileInfo info = new FileInfo(MapToFilesystem(context.Request.QueryString));
                        if (info.Exists)
                        {
                            info.Delete();
                            context.Response.StatusCode = FtpStatusCode.FileActionOK;
                        }
                        else
                        {
                            context.Response.StatusCode = FtpStatusCode.ActionNotTakenFilenameNotAllowed;
                        }
                    }
                    break;

                    case WebRequestMethodsEx.Ftp.RenameFrom:
                    {
                        FileInfo fInfo = new FileInfo(MapToFilesystem(context.Request.QueryString));

                        String fsPath = MapToFilesystem(context.Request.QueryString);
                        if (fsPath[fsPath.Length - 1] == Path.DirectorySeparatorChar)
                        {
                            fsPath = fsPath.Substring(0, fsPath.Length - 1);
                        }
                        DirectoryInfo dInfo = new DirectoryInfo(fsPath);

                        if (fInfo.Exists)
                        {
                            context.Response.StatusCode = FtpStatusCode.FileCommandPending;
                            context.Response.OutputStream.Close();

                            context = this.GetContext();

                            if (context.Request.Method != WebRequestMethodsEx.Ftp.RenameTo)
                            {
                                context.Response.StatusCode = FtpStatusCode.BadCommandSequence;
                            }
                            else
                            {
                                File.Move(fInfo.FullName, MapToFilesystem(context.Request.QueryString));

                                context.Response.StatusCode = FtpStatusCode.FileActionOK;
                            }
                        }
                        else if (dInfo.Exists)
                        {
                            context.Response.StatusCode = FtpStatusCode.FileCommandPending;
                            context.Response.OutputStream.Close();

                            context = this.GetContext();

                            if (context.Request.Method != WebRequestMethodsEx.Ftp.RenameTo)
                            {
                                context.Response.StatusCode = FtpStatusCode.BadCommandSequence;
                            }
                            else
                            {
                                fsPath = MapToFilesystem(context.Request.QueryString);
                                if (fsPath[fsPath.Length - 1] == Path.DirectorySeparatorChar)
                                {
                                    fsPath = fsPath.Substring(0, fsPath.Length - 1);
                                }

                                Directory.Move(dInfo.FullName, fsPath);

                                context.Response.StatusCode = FtpStatusCode.FileActionOK;
                            }
                        }
                        else
                        {
                            context.Response.StatusCode = FtpStatusCode.ActionNotTakenFilenameNotAllowed;
                        }
                    }
                    break;

                    default:
                        context.Response.StatusCode = FtpStatusCode.FileActionAborted;
                        break;
                    }
                }
                catch (Exception e)
                {
                    Logging.Print("could not process command: " + e);

                    context.Response.StatusCode = FtpStatusCode.ActionAbortedLocalProcessingError;
                }

                context.Response.OutputStream.Close();
            }
        }
コード例 #10
0
        /// <summary>
        /// Control thread
        /// TODO: separate the functionalities into functions to reduce maintenance cost
        /// </summary>
        private void WorkerThread()
        {
            FtpCommand command;
            FtpState   state = FtpState.WaitUser;

            string tempName = null;         // store old name for "rename from" command
            string response;
            int    timeout = 0;

            try
            {
                while (m_IsAlive)
                {
                    if (m_IsDisposed)
                    {
                        break;
                    }
                    else if (!m_Welcomed)
                    {
                        response = "220 MyFTP " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString() +
                                   " Server [" + m_HostIp.ToString() + "] \r\n";
                        m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                        m_Welcomed = true;
                    }
                    else if (m_CommandSocket == null)
                    {
                        Logging.Print("Session socket has been closed.");
                        break;
                    }
                    else if (m_CommandSocket.Poll(1000, SelectMode.SelectRead))
                    {
                        if (m_CommandSocket.Available == 0)
                        {
                            Logging.Print("REMOTE DISCONNECT " + m_CommandSocket.RemoteEndPoint.ToString());
                            m_IsAlive = false;
                            break;
                        }
                        // read until find the end of a line
                        command = FtpCommandCreator.Create(ReadCommand());

                        if (command == null)
                        {
                            break;
                        }
                        else
                        {
                            switch (command.Type)
                            {
                            case FtpCommandType.User:
                                response = "331 " + command.Content + " login ok \r\n";
                                m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                state    = FtpState.WaitPwd;
                                tempName = command.Content;
                                break;

                            case FtpCommandType.Pass:
                                if (state != FtpState.WaitPwd)
                                {
                                    response = "332 Need Account for Login.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else
                                {
                                    UserAuthenticatorArgs args = new UserAuthenticatorArgs(tempName, command.Content);
                                    FtpListener.RaiseEvent(this, args);
                                    if (args.Result == UserAuthenticationResult.Approved)
                                    {
                                        User.UserName = tempName;
                                        User.PassWord = command.Content;
                                        response      = "230 access granted for " + User.UserName + ", restrictions apply. \r\n";
                                        m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                        state = FtpState.WaitCommand;
                                        break;
                                    }
                                    else
                                    {
                                        response = "530 Login incorrect. \r\n";
                                        m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                        state = FtpState.WaitCommand;
                                        break;
                                    }
                                }

                            case FtpCommandType.Cwd:
                                if (state == FtpState.WaitPwd)
                                {
                                    response = "331 Need Password.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitUser)
                                {
                                    response = "332 Need Account for Login.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitCommand)
                                {
                                    if (command.Content == null)
                                    {
                                        response = m_BadSequence;
                                        m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                        break;
                                    }
                                    else
                                    {
                                        FtpListenerRequest request = new FtpListenerRequest(WebRequestMethodsEx.Ftp.ChangeDirectory, m_CurrentDirectory.Combine(command.Content).GetNetPath(), this);
                                        FtpListenerContext context = new FtpListenerContext(this, request);
                                        m_SendContext.AddContext(context);
                                        break;
                                    }
                                }
                                else
                                {
                                    response = m_BadSequence;
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }

                            case FtpCommandType.Quit:
                                m_IsAlive = false;
                                CloseDataChannel();
                                response = "221 Goodbye.\r\n";
                                m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                m_CommandSocket.Close();
                                m_CommandSocket = null;
                                break;

                            case FtpCommandType.Pasv:
                                if (state == FtpState.WaitPwd)
                                {
                                    response = "331 Need Password.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitCommand)
                                {
                                    CloseDataChannel();
                                    m_DataThread = new Thread(PassiveThread);
                                    m_DataThread.Start();
                                    m_DataReadyEvent.WaitOne();                    // wait until port has been successfully assigned

                                    byte[] addrs = m_HostIp.GetAddressBytes();

                                    int upper = m_HostPort / 256;
                                    int lower = m_HostPort % 256;
                                    if (addrs.Length == 4)     //IPv4
                                    {
                                        response = "227 Entering Passive Mode (";
                                        foreach (int i in addrs)
                                        {
                                            response += i.ToString() + ",";
                                        }
                                        response += upper.ToString() + "," + lower.ToString() + ")\r\n";
                                    }
                                    else     // currently do not support IPv6
                                    {
                                        throw new NotImplementedException("currently does not support IPv6");
                                    }
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else
                                {
                                    response = m_BadSequence;
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }

                            case FtpCommandType.Type:
                                if (state == FtpState.WaitPwd)
                                {
                                    response = "331 Need Password.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitCommand)
                                {
                                    response = "200 Command OK.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else
                                {
                                    response = m_BadSequence;
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }

                            case FtpCommandType.List:
                                if (!m_DataModeON)
                                {
                                    response = "425 Use PORT or PASV first.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitCommand)
                                {
                                    response = "150 Opening UTF8 mode data connection for *** \r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    FtpListenerRequest request = new FtpListenerRequest(WebRequestMethods.Ftp.ListDirectoryDetails, m_CurrentDirectory.Combine(command.Content).GetNetPath(), this);
                                    FtpListenerContext context = new FtpListenerContext(this, request);
                                    m_SendContext.AddContext(context);
                                    break;
                                }
                                else
                                {
                                    response = m_BadSequence;
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }

                            case FtpCommandType.NList:
                                if (!m_DataModeON)
                                {
                                    response = "425 Use PORT or PASV first.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitCommand)
                                {
                                    response = "150 Opening UTF8 mode data connection for *** \r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    FtpListenerRequest request = new FtpListenerRequest(WebRequestMethods.Ftp.ListDirectory, m_CurrentDirectory.Combine(command.Content).GetNetPath(), this);
                                    FtpListenerContext context = new FtpListenerContext(this, request);
                                    m_SendContext.AddContext(context);
                                    break;
                                }
                                else
                                {
                                    response = m_BadSequence;
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }

                            case FtpCommandType.Port:
                                if (state == FtpState.WaitPwd)
                                {
                                    response = "331 Need Password.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitCommand && command.Content != null)
                                {
                                    CloseDataChannel();
                                    string[] epad = command.Content.Split(new char[] { ',' });
                                    if (epad.Length != 6)
                                    {
                                        response = "500 Invalid PORT command.\r\n";
                                        m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    }
                                    else
                                    {
                                        try
                                        {
                                            m_ClientIp = IPAddress.Parse(epad[0] + "." + epad[1] + "." + epad[2] + "." + epad[3]);

                                            m_ClientPort = Int32.Parse(epad[4]) * 256 + Int32.Parse(epad[5]);
                                            if (m_ClientPort <= 0 || m_ClientPort > 65535)
                                            {
                                                response = "500 Invalid PORT command.\r\n";
                                                m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                            }
                                            else
                                            {
                                                m_ActThreadW = true;
                                                m_DataThread = new Thread(ActiveThread);
                                                m_DataThread.Start();

                                                response = "200 PORT command successful.\r\n";
                                                m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                            }
                                        }
                                        catch (Exception)
                                        {
                                            response = "500 Invalid PORT command.\r\n";
                                            m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                        }
                                    }
                                    break;
                                }
                                else
                                {
                                    response = m_BadSequence;
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }

                            case FtpCommandType.Sys:
                                if (state == FtpState.WaitPwd)
                                {
                                    response = "331 Need Password.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitCommand)
                                {
                                    response = "215 System Type: EMIC\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else
                                {
                                    response = m_BadSequence;
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }

                            case FtpCommandType.Feature:
                                if (state == FtpState.WaitPwd)
                                {
                                    response = "331 Need Password.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitCommand)
                                {
                                    response = "211-Features:\r\n SIZE\r\n211 End\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else
                                {
                                    response = m_BadSequence;
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }

                            case FtpCommandType.Pwd:
                                if (state == FtpState.WaitPwd)
                                {
                                    response = "331 Need Password.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitCommand)
                                {
                                    response = "257 \"" + m_CurrentDirectory.GetNetPath() + "\" is the current directory. \r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else
                                {
                                    response = m_BadSequence;
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }

                            case FtpCommandType.Retr:
                                if (state == FtpState.WaitPwd)
                                {
                                    response = "331 Need Password.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitCommand)
                                {
                                    if (!m_DataModeON)
                                    {
                                        response = "425 Use PORT or PASV first.\r\n";
                                        m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                        break;
                                    }
                                    response = "150 Opening BINARY mode data connection for " + command.Content + ". \r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    FtpListenerRequest request = new FtpListenerRequest(WebRequestMethods.Ftp.DownloadFile, m_CurrentDirectory.Combine(command.Content).GetNetPath(), this);
                                    FtpListenerContext context = new FtpListenerContext(this, request);
                                    m_SendContext.AddContext(context);
                                    break;
                                }
                                else
                                {
                                    response = m_BadSequence;
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }

                            case FtpCommandType.Opts:
                                if (state == FtpState.WaitPwd)
                                {
                                    response = "331 Need Password.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitCommand)
                                {
                                    if (command.Content == "utf8")
                                    {
                                        response = "213 Always in utf8 mode \r\n";
                                    }
                                    else
                                    {
                                        response = "550 Requested action not taken. Mode not support. \r\n";
                                    }
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else
                                {
                                    response = m_BadSequence;
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }

                            case FtpCommandType.Size:
                                if (state == FtpState.WaitPwd)
                                {
                                    response = "331 Need Password.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitCommand)
                                {
                                    FtpListenerRequest request = new FtpListenerRequest(WebRequestMethods.Ftp.GetFileSize, m_CurrentDirectory.Combine(command.Content).GetNetPath(), this);
                                    FtpListenerContext context = new FtpListenerContext(this, request);
                                    m_SendContext.AddContext(context);
                                    break;
                                }
                                else
                                {
                                    response = m_BadSequence;
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }

                            case FtpCommandType.Store:
                                if (state == FtpState.WaitPwd)
                                {
                                    response = "331 Need Password.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitCommand)
                                {
                                    if (!m_DataModeON)
                                    {
                                        response = "425 Use PORT or PASV first.\r\n";
                                        m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                        break;
                                    }
                                    response = "150 Opening BINARY mode data connection for " + command.Content + ". \r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    FtpListenerRequest request = new FtpListenerRequest(WebRequestMethods.Ftp.UploadFile, m_CurrentDirectory.Combine(command.Content).GetNetPath(), this);
                                    FtpListenerContext context = new FtpListenerContext(this, request);
                                    m_SendContext.AddContext(context);
                                    break;
                                }
                                else
                                {
                                    response = m_BadSequence;
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }

                            case FtpCommandType.Noop:
                                response = "200 NOOP command successful. \r\n";
                                m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                break;

                            case FtpCommandType.Delete:
                                if (state == FtpState.WaitPwd)
                                {
                                    response = "331 Need Password.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitCommand)
                                {
                                    FtpListenerRequest request = new FtpListenerRequest(WebRequestMethods.Ftp.DeleteFile, m_CurrentDirectory.Combine(command.Content).GetNetPath(), this);
                                    FtpListenerContext context = new FtpListenerContext(this, request);
                                    m_SendContext.AddContext(context);
                                    break;
                                }
                                else
                                {
                                    response = m_BadSequence;
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }

                            case FtpCommandType.MkDir:
                                if (state == FtpState.WaitPwd)
                                {
                                    response = "331 Need Password.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitCommand)
                                {
                                    FtpListenerRequest request = new FtpListenerRequest(WebRequestMethods.Ftp.MakeDirectory, m_CurrentDirectory.Combine(command.Content).GetNetPath(), this);
                                    FtpListenerContext context = new FtpListenerContext(this, request);
                                    m_SendContext.AddContext(context);
                                    break;
                                }
                                else
                                {
                                    response = m_BadSequence;
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }

                            case FtpCommandType.Rmd:
                                if (state == FtpState.WaitPwd)
                                {
                                    response = "331 Need Password.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitCommand)
                                {
                                    FtpListenerRequest request = new FtpListenerRequest(WebRequestMethods.Ftp.RemoveDirectory, m_CurrentDirectory.Combine(command.Content).GetNetPath(), this);
                                    FtpListenerContext context = new FtpListenerContext(this, request);
                                    m_SendContext.AddContext(context);
                                    break;
                                }
                                else
                                {
                                    response = m_BadSequence;
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }

                            case FtpCommandType.Rnfr:
                                if (state == FtpState.WaitPwd)
                                {
                                    response = "331 Need Password.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitCommand)
                                {
                                    FtpListenerRequest request = new FtpListenerRequest(WebRequestMethodsEx.Ftp.RenameFrom, m_CurrentDirectory.Combine(command.Content).GetNetPath(), this);
                                    FtpListenerContext context = new FtpListenerContext(this, request);
                                    m_SendContext.AddContext(context);
                                    break;
                                }
                                else
                                {
                                    response = m_BadSequence;
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }

                            case FtpCommandType.Rnto:
                                if (state == FtpState.WaitPwd)
                                {
                                    response = "331 Need Password.\r\n";
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }
                                else if (state == FtpState.WaitCommand)
                                {
                                    FtpListenerRequest request = new FtpListenerRequest(WebRequestMethodsEx.Ftp.RenameTo, m_CurrentDirectory.Combine(command.Content).GetNetPath(), this);
                                    FtpListenerContext context = new FtpListenerContext(this, request);
                                    m_SendContext.AddContext(context);
                                    break;
                                }
                                else
                                {
                                    response = m_BadSequence;
                                    m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                    break;
                                }

                            default:
                                response = "502 Command not implemented. \r\n";
                                if (state == FtpState.WaitPwd)
                                {
                                    state = FtpState.WaitUser;
                                }
                                m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                                break;
                            }
                        }
                        // reset time out
                        timeout = 0;
                    }
                    else if (m_CommandSocket.Poll(1000, SelectMode.SelectError))
                    {
                        Logging.Print("Disconnected unproperly.");
                        break;
                    }
                    else
                    {
                        if (!m_Welcomed)
                        {
                            response = "220 MyFTP " + typeof(FtpListenerSession).Assembly.GetName().Version.ToString() +
                                       " Server [" + m_HostIp.ToString() + "] \r\n";
                            m_CommandSocket.Send(Encoding.UTF8.GetBytes(response));
                            m_Welcomed = true;
                        }
                        else
                        {
                            if (SessionTimeOut != -1)
                            {
                                if (timeout > SessionTimeOut)
                                {
                                    m_IsAlive = false;
                                    Logging.Print("Connection time out.");
                                    break;
                                }
                                timeout += 50;
                            }
                            Thread.Sleep(50);
                        }
                    }
                }
            }
            catch (SocketException se)
            {
                Logging.Print("Control Socket Exception : " + se.ErrorCode.ToString());
            }
            catch (IOException ioe)
            {
                Logging.Print("IOException: " + ioe.Message);
            }
            finally
            {
                m_IsAlive = false;
                if (m_CommandSocket != null)
                {
                    m_CommandSocket.Close();
                    m_CommandSocket = null;
                }
                if (m_ListenSocket != null)
                {
                    m_ListenSocket.Close();
                    m_CommandSocket = null;
                }
                Logging.Print("Client Disconnected.");
            }
        }