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}"); } }
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); } }
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; }
/// <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"); } }