diff --git a/mailnews/local/src/nsPop3Protocol.cpp b/mailnews/local/src/nsPop3Protocol.cpp index 76f06b6feb13..29a0be33d8d0 100644 --- a/mailnews/local/src/nsPop3Protocol.cpp +++ b/mailnews/local/src/nsPop3Protocol.cpp @@ -77,6 +77,10 @@ #include "nsEscape.h" #include "nsMsgUtils.h" #include "nsISignatureVerifier.h" +#include "nsIPrefBranch.h" +#include "nsIPrefService.h" +#include "nsIPrefLocalizedString.h" +#include "nsISocketTransport.h" #define EXTRA_SAFETY_SPACE 3096 @@ -509,7 +513,9 @@ nsPop3Protocol::nsPop3Protocol(nsIURI* aURL) m_totalBytesReceived(0), m_lineStreamBuffer(nsnull), m_pop3ConData(nsnull), - m_password_already_sent(PR_FALSE) + m_password_already_sent(PR_FALSE), + m_responseTimer(nsnull), + m_responseTimeout(45) { SetLookingForCRLF(MSG_LINEBREAK_LEN == 2); m_ignoreCRLFs = PR_TRUE; @@ -528,6 +534,7 @@ nsresult nsPop3Protocol::Initialize(nsIURI * aURL) m_totalFolderSize = 0; m_totalDownloadSize = 0; m_totalBytesReceived = 0; + m_responseTimeout = 45; if (aURL) { @@ -586,6 +593,15 @@ nsresult nsPop3Protocol::Initialize(nsIURI * aURL) if (!POP3LOGMODULE) POP3LOGMODULE = PR_NewLogModule("POP3"); + // Read in preferences + nsCOMPtr prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID)); + if (prefBranch) + { + prefBranch->GetIntPref("mail.pop3_response_timeout", &m_responseTimeout); + PR_LOG(POP3LOGMODULE, PR_LOG_ALWAYS, + ("mail.pop3_response_timeout=%d", m_responseTimeout)); + } + m_lineStreamBuffer = new nsMsgLineStreamBuffer(OUTPUT_BUFFER_SIZE, PR_TRUE); if(!m_lineStreamBuffer) return NS_ERROR_OUT_OF_MEMORY; @@ -727,6 +743,15 @@ nsresult nsPop3Protocol::GetPassword(char ** aPassword, PRBool *okayValue) return rv; } +NS_IMETHODIMP nsPop3Protocol::OnTransportStatus(nsITransport *aTransport, nsresult aStatus, PRUint32 aProgress, PRUint32 aProgressMax) +{ + // When the socket connection is established, start the response timer. + if (aStatus == NS_NET_STATUS_CONNECTED_TO) + SetResponseTimer(); + + return nsMsgProtocol::OnTransportStatus(aTransport, aStatus, aProgress, aProgressMax); +} + // stop binding is a "notification" informing us that the stream associated with aURL is going away. NS_IMETHODIMP nsPop3Protocol::OnStopRequest(nsIRequest *request, nsISupports * aContext, nsresult aStatus) { @@ -3331,6 +3356,7 @@ nsresult nsPop3Protocol::ProcessProtocolState(nsIURI * url, nsIInputStream * aIn PRInt32 status = 0; nsCOMPtr mailnewsurl = do_QueryInterface(m_url); + CancelResponseTimer(); PR_LOG(POP3LOGMODULE, PR_LOG_ALWAYS, ("Entering NET_ProcessPop3 %d", aLength)); @@ -3742,6 +3768,8 @@ nsresult nsPop3Protocol::ProcessProtocolState(nsIURI * url, nsIInputStream * aIn } /* end while */ + SetResponseTimer(); + return NS_OK; } @@ -3781,3 +3809,35 @@ NS_IMETHODIMP nsPop3Protocol::CheckMessage(const char *aUidl, PRBool *aBool) *aBool = uidlEntry ? PR_TRUE : PR_FALSE; return NS_OK; } + +void OnResponseTimeout(nsITimer *timer, void *aPop3Protocol) +{ + nsPop3Protocol *pop3Protocol = (nsPop3Protocol *) aPop3Protocol; + + PR_LOG(POP3LOGMODULE, PR_LOG_ALWAYS, + ("OnResponseTimeout: username=%s", pop3Protocol->GetUsername())); + + // Cancel this connection to force it to drop. + pop3Protocol->Cancel(NS_BINDING_FAILED); +} + +void nsPop3Protocol::SetResponseTimer() +{ + // Cancel outstanding timer since it can't be reset. + CancelResponseTimer(); + + // Setup new response timer + PRUint32 timeInMSUint32 = m_responseTimeout * 1000; + m_responseTimer = do_CreateInstance("@mozilla.org/timer;1"); + m_responseTimer->InitWithFuncCallback(OnResponseTimeout, (void*)this, + timeInMSUint32, nsITimer::TYPE_ONE_SHOT); +} + +void nsPop3Protocol::CancelResponseTimer() +{ + // Cancel outstanding response timer + if (m_responseTimer) { + m_responseTimer->Cancel(); + m_responseTimer = nsnull; + } +} diff --git a/mailnews/local/src/nsPop3Protocol.h b/mailnews/local/src/nsPop3Protocol.h index 6bb174e02c59..2d6cc03da93b 100644 --- a/mailnews/local/src/nsPop3Protocol.h +++ b/mailnews/local/src/nsPop3Protocol.h @@ -51,6 +51,7 @@ #include "nsIMsgStatusFeedback.h" #include "nsIMsgFolder.h" // TO include biffState enum. Change to bool later... #include "nsIAuthModule.h" +#include "nsITimer.h" #include "prerror.h" #include "plhash.h" @@ -297,6 +298,7 @@ public: nsresult GetPassword(char ** aPassword, PRBool *okayValue); + NS_IMETHOD OnTransportStatus(nsITransport *transport, nsresult status, PRUint32 progress, PRUint32 progressMax); NS_IMETHOD OnStopRequest(nsIRequest *request, nsISupports * aContext, nsresult aStatus); NS_IMETHOD Cancel(nsresult status); // for nsMsgLineBuffer @@ -357,6 +359,12 @@ private: PRInt32 m_origAuthFlags; PRInt32 m_listpos; + // Response timer to drop hung connections + nsCOMPtr m_responseTimer; + PRInt32 m_responseTimeout; // in seconds + void SetResponseTimer(); + void CancelResponseTimer(); + ////////////////////////////////////////////////////////////////////////////////////////// // Begin Pop3 protocol state handlers ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/mailnews/mailnews.js b/mailnews/mailnews.js index 51d0bdc0a028..8f28be083774 100644 --- a/mailnews/mailnews.js +++ b/mailnews/mailnews.js @@ -107,6 +107,7 @@ pref("mail.default_cc", ""); pref("mail.default_fcc", ""); // maibox:URL or Imap://Host/OnLineFolderName pref("mail.check_new_mail", false); pref("mail.pop3_gets_new_mail", false); +pref("mail.pop3_response_timeout", 45); // in seconds pref("mail.check_time", 10); pref("mail.pop_name", ""); pref("mail.remember_password", false);