diff -Nur Filezilla3/src/engine/ControlSocket.h Filezilla3.patch/src/engine/ControlSocket.h
--- Filezilla3/src/engine/ControlSocket.h	Thu Aug 16 12:54:33 2007
+++ Filezilla3.patch/src/engine/ControlSocket.h	Thu Aug 16 12:55:42 2007
@@ -115,6 +115,8 @@
 	virtual int Chmod(const CChmodCommand& command) { return FZ_REPLY_NOTSUPPORTED; }
 	virtual bool Connected() const = 0;
 
+	virtual int KeepAlive(const CKeepAliveCommand& command) { return FZ_REPLY_OK; }
+
 	// If m_pCurrentOpData is zero, this function returns the current command
 	// from the engine.
 	enum Command GetCurrentCommandId() const;
diff -Nur Filezilla3/src/engine/FileZillaEngine.cpp Filezilla3.patch/src/engine/FileZillaEngine.cpp
--- Filezilla3/src/engine/FileZillaEngine.cpp	Thu Aug 16 12:54:35 2007
+++ Filezilla3.patch/src/engine/FileZillaEngine.cpp	Thu Aug 16 12:55:50 2007
@@ -70,6 +70,9 @@
 	case cmd_chmod:
 		res = Chmod(reinterpret_cast<const CChmodCommand&>(command));
 		break;
+	case cmd_keepalive:
+		res = KeepAlive(reinterpret_cast<const CKeepAliveCommand &>(command));
+		break;
 	default:
 		return FZ_REPLY_SYNTAXERROR;
 	}
diff -Nur Filezilla3/src/engine/commands.cpp Filezilla3.patch/src/engine/commands.cpp
--- Filezilla3/src/engine/commands.cpp	Thu Aug 16 12:54:35 2007
+++ Filezilla3.patch/src/engine/commands.cpp	Thu Aug 16 12:55:57 2007
@@ -10,6 +10,16 @@
 	return m_Server;
 }
 
+CKeepAliveCommand::CKeepAliveCommand(bool keepAlive /*=true*/)
+    : m_keepAlive(keepAlive)
+{
+}
+
+bool CKeepAliveCommand::IsKeepAlive() const
+{
+	return m_keepAlive;
+}
+
 CListCommand::CListCommand(bool refresh /*=false*/)
 	: m_refresh(refresh)
 {
diff -Nur Filezilla3/src/engine/engineprivate.cpp Filezilla3.patch/src/engine/engineprivate.cpp
--- Filezilla3/src/engine/engineprivate.cpp	Thu Aug 16 12:54:35 2007
+++ Filezilla3.patch/src/engine/engineprivate.cpp	Thu Aug 16 12:56:05 2007
@@ -525,6 +525,12 @@
 	return m_pControlSocket->Chmod(command);
 }
 
+int CFileZillaEnginePrivate::KeepAlive(const CKeepAliveCommand& command)
+{
+	m_pCurrentCommand = command.Clone();
+	return m_pControlSocket->KeepAlive(command);
+}
+
 void CFileZillaEnginePrivate::SendDirectoryListingNotification(const CServerPath& path, bool onList, bool modified, bool failed)
 {
 	wxASSERT(m_pControlSocket);
diff -Nur Filezilla3/src/engine/ftpcontrolsocket.cpp Filezilla3.patch/src/engine/ftpcontrolsocket.cpp
--- Filezilla3/src/engine/ftpcontrolsocket.cpp	Thu Aug 16 12:54:35 2007
+++ Filezilla3.patch/src/engine/ftpcontrolsocket.cpp	Thu Aug 16 12:55:24 2007
@@ -24,8 +24,11 @@
 #define LOGON_CUSTOMCOMMANDS 10
 #define LOGON_DONE		11
 
+#define KEEPALIVE_TIMER_ID wxID_HIGHEST + 5
+
 BEGIN_EVENT_TABLE(CFtpControlSocket, CRealControlSocket)
 EVT_FZ_EXTERNALIPRESOLVE(wxID_ANY, CFtpControlSocket::OnExternalIPAddress)
+EVT_TIMER(wxID_ANY, CFtpControlSocket::OnTimer)
 END_EVENT_TABLE();
 
 CRawTransferOpData::CRawTransferOpData()
@@ -137,6 +140,8 @@
 	m_pTlsSocket = 0;
 	m_protectDataChannel = false;
 	m_lastTypeBinary = -1;
+	m_bEnableKeepAlive = false;
+	m_keepAliveTimer.SetOwner(this, KEEPALIVE_TIMER_ID);
 }
 
 CFtpControlSocket::~CFtpControlSocket()
@@ -147,12 +152,16 @@
 {
 	LogMessage(Debug_Verbose, _T("CFtpControlSocket::OnReceive()"));
 
+	m_keepAliveStopWatch.Start();
+
 	m_pBackend->Read(m_receiveBuffer + m_bufferLen, RECVBUFFERSIZE - m_bufferLen);
 	
 	if (m_pBackend->Error())
 	{
 		if (m_pBackend->LastError() != wxSOCKET_WOULDBLOCK)
 		{
+			m_bEnableKeepAlive = false;
+			m_keepAliveTimer.Stop();
 			LogMessage(::Error, _("Disconnected from server"));
 			DoClose();
 		}
@@ -386,6 +395,9 @@
 	case cmd_rawtransfer:
 		TransferParseResponse();
 		break;
+	case cmd_keepalive:
+		KeepAliveParseResponse();
+		break;
 	case cmd_none:
 		LogMessage(Debug_Verbose, _T("Out-of-order reply, ignoring."));
 		break;
@@ -798,6 +810,7 @@
 		LogMessage(::Error, _T("Failed to convert command to 8 bit charset"));
 		return false;
 	}
+	m_keepAliveStopWatch.Start();
 	unsigned int len = (unsigned int)strlen(buffer);
 	bool res = CRealControlSocket::Send(buffer, len);
 	if (res)
@@ -1254,6 +1267,8 @@
 		return DeleteSend(prevResult);
 	case cmd_removedir:
 		return RemoveDirSend(prevResult);
+	case cmd_keepalive:
+		return KeepAliveSend();
 	default:
 		LogMessage(__TFILE__, __LINE__, this, ::Debug_Warning, _T("Unknown opID (%d) in SendNextCommand"), m_pCurOpData->opId);
 		ResetOperation(FZ_REPLY_INTERNALERROR);
@@ -3006,6 +3021,126 @@
 	}
 
 	return FZ_REPLY_WOULDBLOCK;
+}
+
+class CKeepAliveOpData : public COpData
+{
+public:
+	CKeepAliveOpData(const wxString& command)
+		: COpData(cmd_keepalive)
+	{
+		m_command = command;
+	}
+
+	wxString m_command;
+};
+
+int CFtpControlSocket::KeepAlive(const CKeepAliveCommand& command)
+{
+	LogMessage(Debug_Verbose, _T("CFtpControlSocket::KeepAlive"));
+
+	if (command.IsKeepAlive())
+	{
+		if (!m_bEnableKeepAlive)
+		{
+			m_bEnableKeepAlive = true;
+			// FIXME:
+			// read keepalive option here
+			int min_wait = 30;
+			int max_wait = 60;
+			int waitsecond = min_wait + (int)(rand()*(max_wait - min_wait)/(RAND_MAX+1));
+			m_keepAliveTimer.Start(waitsecond * 1000);
+		}
+	}
+	else
+	{
+		if (m_bEnableKeepAlive)
+		{
+			m_bEnableKeepAlive = false;
+			m_keepAliveTimer.Stop();
+		}
+	}
+
+	m_bEnableKeepAlive = true;
+	return FZ_REPLY_OK;
+}
+
+int CFtpControlSocket::DoKeepAlive()
+{
+	LogMessage(Debug_Verbose, _T("CFtpControlSocket::DoKeepAlive"));
+
+	// ignore keepalive for last I/O for socket less than 15 seconds
+	if (m_keepAliveStopWatch.Time() < 15000)
+		return FZ_REPLY_OK;
+	// choose any command
+	wxString commands[5] = {_T("PWD"),_T("REST 0"), _T("NOOP"), _T("STAT"), _T("MKD") };
+	int choice=(rand()*5)/(RAND_MAX+1);
+	m_pCurOpData = new CKeepAliveOpData(commands[choice]);
+
+	return SendNextCommand();
+}
+
+int CFtpControlSocket::KeepAliveSend()
+{
+	LogMessage(Debug_Verbose, _T("CFtpControlSocket::KeepAliveSend"));
+
+	if (!m_pCurOpData)
+	{
+		LogMessage(__TFILE__, __LINE__, this, Debug_Info, _T("Empty m_pCurOpData"));
+		ResetOperation(FZ_REPLY_INTERNALERROR);
+		return FZ_REPLY_ERROR;
+	}
+
+	CDirectoryCache cache;
+	cache.InvalidateServer(*m_pCurrentServer);
+	m_CurrentPath = CServerPath();
+
+	CKeepAliveOpData *pData = static_cast<CKeepAliveOpData *>(m_pCurOpData);
+
+	if (!Send(pData->m_command))
+		return FZ_REPLY_ERROR;
+
+	return FZ_REPLY_WOULDBLOCK;
+}
+
+int CFtpControlSocket::KeepAliveParseResponse()
+{
+	LogMessage(Debug_Verbose, _T("CFtpControlSocket::KeepAliveParseResponse"));
+
+	int code = GetReplyCode();
+	if (code == 2 || code == 3 || code == 5)
+	{
+		ResetOperation(FZ_REPLY_OK);
+		return FZ_REPLY_OK;
+	}
+	else
+	{
+		ResetOperation(FZ_REPLY_ERROR);
+		return FZ_REPLY_ERROR;
+	}
+}
+
+void CFtpControlSocket::OnTimer(wxTimerEvent& event)
+{
+	if (event.GetId() == KEEPALIVE_TIMER_ID)
+	{
+		if (m_keepAliveTimer.IsRunning())
+		{
+			m_keepAliveTimer.Stop();
+			if (m_bEnableKeepAlive) {
+				// FIXME:
+				// need to read the values from options...
+				int min_wait = 30;
+				int max_wait = 60;
+
+				int waitsecond = min_wait + (int)(rand()*(max_wait - min_wait)/(RAND_MAX+1));
+				m_keepAliveTimer.Start(waitsecond * 1000);
+				DoKeepAlive();
+			}
+		}
+	}
+	else
+		CControlSocket::OnTimer(event);
 }
 
 bool CFtpControlSocket::IsMisleadingListResponse() const
diff -Nur Filezilla3/src/engine/ftpcontrolsocket.h Filezilla3.patch/src/engine/ftpcontrolsocket.h
--- Filezilla3/src/engine/ftpcontrolsocket.h	Thu Aug 16 12:54:33 2007
+++ Filezilla3.patch/src/engine/ftpcontrolsocket.h	Thu Aug 16 12:55:33 2007
@@ -24,6 +24,14 @@
 
 protected:
 	
+	bool m_bEnableKeepAlive;
+	wxTimer m_keepAliveTimer;
+	wxStopWatch m_keepAliveStopWatch;
+	virtual int KeepAlive(const CKeepAliveCommand& command);
+	int DoKeepAlive();
+	int KeepAliveParseResponse();
+	int KeepAliveSend();
+
 	virtual int ResetOperation(int nErrorCode);
 
 	virtual int Connect(const CServer &server);
@@ -128,6 +136,7 @@
 
 	DECLARE_EVENT_TABLE();
 	void OnExternalIPAddress(fzExternalIPResolveEvent& event);
+	void OnTimer(wxTimerEvent& event);
 };
 
 class CIOThread;
diff -Nur Filezilla3/src/include/commands.h Filezilla3.patch/src/include/commands.h
--- Filezilla3/src/include/commands.h	Thu Aug 16 12:54:39 2007
+++ Filezilla3.patch/src/include/commands.h	Thu Aug 16 12:56:21 2007
@@ -19,6 +19,7 @@
 	cmd_rename,
 	cmd_chmod,
 	cmd_raw,
+	cmd_keepalive,
 
 	// Only used internally
 	cmd_cwd,
@@ -74,6 +75,15 @@
 	const CServer GetServer() const;
 protected:
 	CServer m_Server;
+};
+
+DECLARE_COMMAND(CKeepAliveCommand, cmd_keepalive)
+	CKeepAliveCommand(bool keepAlive = true);
+
+	bool IsKeepAlive() const;
+
+protected:
+	bool m_keepAlive;
 };
 
 DECLARE_COMMAND(CDisconnectCommand, cmd_disconnect)
diff -Nur Filezilla3/src/include/engineprivate.h Filezilla3.patch/src/include/engineprivate.h
--- Filezilla3/src/include/engineprivate.h	Thu Aug 16 12:54:39 2007
+++ Filezilla3.patch/src/include/engineprivate.h	Thu Aug 16 12:56:27 2007
@@ -69,6 +69,7 @@
 	int Mkdir(const CMkdirCommand& command);
 	int Rename(const CRenameCommand& command);
 	int Chmod(const CChmodCommand& command);
+	int KeepAlive(const CKeepAliveCommand& command);
 
 	int ContinueConnect();
 
diff -Nur Filezilla3/src/interface/Mainfrm.cpp Filezilla3.patch/src/interface/Mainfrm.cpp
--- Filezilla3/src/interface/Mainfrm.cpp	Thu Aug 16 12:54:45 2007
+++ Filezilla3.patch/src/interface/Mainfrm.cpp	Thu Aug 16 12:57:02 2007
@@ -825,7 +825,10 @@
 
 	CServerPath path;
 	path.SetSafePath(COptions::Get()->GetOption(OPTION_LASTSERVERPATH));
-	m_pState->Connect(server, false, path);
+	// FIXME:
+	// read keepalive from option
+	bool keepAlive = true;
+	m_pState->Connect(server, false, path, keepAlive);
 }
 
 void CMainFrame::OnRefresh(wxCommandEvent &event)
@@ -1341,7 +1344,10 @@
 			return;
 	}
 
-	m_pState->Connect(pData->m_server, true, pData->m_remoteDir);
+	// FIXME:
+	// read keepalive from option
+	bool keepAlive = true;
+	m_pState->Connect(pData->m_server, true, pData->m_remoteDir, keepAlive);
 
 	if (pData->m_localDir != _T(""))
 		m_pState->SetLocalDir(pData->m_localDir);
diff -Nur Filezilla3/src/interface/state.cpp Filezilla3.patch/src/interface/state.cpp
--- Filezilla3/src/interface/state.cpp	Thu Aug 16 12:54:45 2007
+++ Filezilla3.patch/src/interface/state.cpp	Thu Aug 16 12:57:13 2007
@@ -247,7 +247,7 @@
 	NotifyHandlers(STATECHANGE_APPLYFILTER);
 }
 
-bool CState::Connect(const CServer& server, bool askBreak, const CServerPath& path /*=CServerPath()*/)
+bool CState::Connect(const CServer& server, bool askBreak, const CServerPath& path /*=CServerPath()*/, bool keepAlive)
 {
 	if (!m_pEngine)
 		return false;
@@ -261,6 +261,8 @@
 
 	m_pCommandQueue->ProcessCommand(new CConnectCommand(server));
 	m_pCommandQueue->ProcessCommand(new CListCommand(path));
+	if (keepAlive)
+		m_pCommandQueue->ProcessCommand(new CKeepAliveCommand(true));
 	
 	COptions::Get()->SetLastServer(server);
 	COptions::Get()->SetOption(OPTION_LASTSERVERPATH, path.GetSafePath());
diff -Nur Filezilla3/src/interface/state.h Filezilla3.patch/src/interface/state.h
--- Filezilla3/src/interface/state.h	Thu Aug 16 12:54:43 2007
+++ Filezilla3.patch/src/interface/state.h	Thu Aug 16 12:57:18 2007
@@ -40,7 +40,7 @@
 	static bool LocalDirHasParent(const wxString& dir);
 	static bool LocalDirIsWriteable(const wxString& dir);
 
-	bool Connect(const CServer& server, bool askBreak, const CServerPath& path = CServerPath());
+	bool Connect(const CServer& server, bool askBreak, const CServerPath& path = CServerPath(), bool keepAlive = false);
 
 	bool SetRemoteDir(const CDirectoryListing *m_pDirectoryListing, bool modified = false);
 	const CDirectoryListing *GetRemoteDir() const;
