diff --git a/mozilla/netwerk/base/public/netCore.h b/mozilla/netwerk/base/public/netCore.h index b536545cb98..71a1eb7e067 100644 --- a/mozilla/netwerk/base/public/netCore.h +++ b/mozilla/netwerk/base/public/netCore.h @@ -42,7 +42,7 @@ #define NS_ERROR_NOT_CONNECTED \ NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 12) -/* NS_ERROR_CONNECTION_REFUSED and NS_ERROR_NET_TIMEOUT moved to nsISocketTransportService.idl */ +/* see nsISocketTransportService.idl for other errors */ #define NS_ERROR_IN_PROGRESS \ NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 15) diff --git a/mozilla/netwerk/base/public/nsISocketTransportService.idl b/mozilla/netwerk/base/public/nsISocketTransportService.idl index 012810223a3..bed0bb90ef2 100644 --- a/mozilla/netwerk/base/public/nsISocketTransportService.idl +++ b/mozilla/netwerk/base/public/nsISocketTransportService.idl @@ -96,10 +96,15 @@ interface nsISocketTransportService : nsISupports {0x92, 0xb6, 0x00, 0x10, 0x5a, 0x1b, 0x0d, 0x64} \ } +// if a socket connection attempt fails (eg. no server listening at specified host:port) #define NS_ERROR_CONNECTION_REFUSED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 13) +// if a socket connection was lost due to a timeout error (eg. PR_Poll times out) #define NS_ERROR_NET_TIMEOUT NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 14) +// if a socket connection was lost due to a network reset (eg. PR_Poll sets PR_POLL_ERR) +#define NS_ERROR_NET_RESET NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 20) + /** * Status nsresult codes: used with nsIProgressEventSink::OnStatus */ diff --git a/mozilla/netwerk/base/src/nsSocketTransport.cpp b/mozilla/netwerk/base/src/nsSocketTransport.cpp index fb25addd6e3..3c4f7d674ae 100644 --- a/mozilla/netwerk/base/src/nsSocketTransport.cpp +++ b/mozilla/netwerk/base/src/nsSocketTransport.cpp @@ -959,12 +959,12 @@ nsSocketTransport::doReadWrite(PRInt16 aSelectFlags) if (PR_POLL_EXCEPT & aSelectFlags) { LOG(("nsSocketTransport: [this=%x] received PR_POLL_EXCEPT\n", this)); // The socket will be closed when we reach eSocketState_Error. - return NS_BINDING_FAILED; + return NS_ERROR_NET_RESET; } if (PR_POLL_ERR & aSelectFlags) { LOG(("nsSocketTransport: [this=%x] received PR_POLL_ERR\n", this)); // The socket will be closed when we reach eSocketState_Error. - return NS_BINDING_FAILED; + return NS_ERROR_NET_RESET; } if (PR_POLL_HUP & aSelectFlags) { LOG(("nsSocketTransport: [this=%x] received PR_POLL_HUP\n", this)); diff --git a/mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp b/mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp index 27b9091f0be..815ae03d2c3 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHttpTransaction.cpp @@ -30,6 +30,7 @@ #include "nsHttpChunkedDecoder.h" #include "nsIStringStream.h" #include "nsIFileStream.h" +#include "nsISocketTransportService.h" #include "pratom.h" #include "plevent.h" @@ -183,43 +184,12 @@ nsHttpTransaction::OnDataReadable(nsIInputStream *is) // check if this transaction needs to be restarted if (mPrematureEOF) { - // limit the number of restart attempts - bug 92224 - if (++mRestartCount >= nsHttpHandler::get()->MaxRequestAttempts()) { - LOG(("reached max request attempts, failing transaction @%x\n", this)); - return NS_BINDING_FAILED; - } - mPrematureEOF = PR_FALSE; - - LOG(("restarting transaction @%x\n", this)); - - // rewind streams in case we already wrote out the request - nsCOMPtr ras = do_QueryInterface(mReqHeaderStream); - if (ras) - ras->Seek(PR_SEEK_SET, 0); - ras = do_QueryInterface(mReqUploadStream); - if (ras) - ras->Seek(PR_SEEK_SET, 0); - - // just in case the connection is holding the last reference to us... - NS_ADDREF_THIS(); - - // we don't want the connection to send anymore notifications to us. - mConnection->DropTransaction(); - - nsHttpConnectionInfo *ci = mConnection->ConnectionInfo(); - NS_ADDREF(ci); - - // we must release the connection before calling initiate transaction - // since we will be getting a new connection. - NS_RELEASE(mConnection); - - rv = nsHttpHandler::get()->InitiateTransaction(this, ci); - NS_ASSERTION(NS_SUCCEEDED(rv), "InitiateTransaction failed"); - - NS_RELEASE(ci); - NS_RELEASE_THIS(); - return NS_BINDING_ABORTED; + rv = Restart(); + // if successfully restarted, then return an error to abort the + // socket transport. + if (NS_SUCCEEDED(rv)) + rv = NS_BINDING_ABORTED; } return rv; @@ -232,6 +202,14 @@ nsHttpTransaction::OnStopTransaction(nsresult status) LOG(("nsHttpTransaction::OnStopTransaction [this=%x status=%x]\n", this, status)); + // if the connection was reset before we read any part of the response, + // then we must try to restart the transaction. + if ((status == NS_ERROR_NET_RESET) && (mContentRead == 0)) { + // if restarting fails, then we must notify our listener. + if (NS_SUCCEEDED(Restart())) + return NS_OK; + } + mStatus = status; if (mListener) { @@ -581,6 +559,48 @@ nsHttpTransaction::DeleteThis_EventCleanupFunc(PLEvent *ev) // nsHttpTransaction::nsISupports //----------------------------------------------------------------------------- +nsresult +nsHttpTransaction::Restart() +{ + nsresult rv; + + // limit the number of restart attempts - bug 92224 + if (++mRestartCount >= nsHttpHandler::get()->MaxRequestAttempts()) { + LOG(("reached max request attempts, failing transaction @%x\n", this)); + return NS_BINDING_FAILED; + } + + LOG(("restarting transaction @%x\n", this)); + + // rewind streams in case we already wrote out the request + nsCOMPtr ras = do_QueryInterface(mReqHeaderStream); + if (ras) + ras->Seek(PR_SEEK_SET, 0); + ras = do_QueryInterface(mReqUploadStream); + if (ras) + ras->Seek(PR_SEEK_SET, 0); + + // just in case the connection is holding the last reference to us... + NS_ADDREF_THIS(); + + // we don't want the connection to send anymore notifications to us. + mConnection->DropTransaction(); + + nsHttpConnectionInfo *ci = mConnection->ConnectionInfo(); + NS_ADDREF(ci); + + // we must release the connection before calling initiate transaction + // since we will be getting a new connection. + NS_RELEASE(mConnection); + + rv = nsHttpHandler::get()->InitiateTransaction(this, ci); + NS_ASSERTION(NS_SUCCEEDED(rv), "InitiateTransaction failed"); + + NS_RELEASE(ci); + NS_RELEASE_THIS(); + return NS_OK; +} + NS_IMPL_THREADSAFE_ADDREF(nsHttpTransaction) NS_IMETHODIMP_(nsrefcnt) diff --git a/mozilla/netwerk/protocol/http/src/nsHttpTransaction.h b/mozilla/netwerk/protocol/http/src/nsHttpTransaction.h index 68da1bd8fa0..57ee834f98a 100644 --- a/mozilla/netwerk/protocol/http/src/nsHttpTransaction.h +++ b/mozilla/netwerk/protocol/http/src/nsHttpTransaction.h @@ -90,6 +90,7 @@ public: nsresult OnStopTransaction(nsresult); private: + nsresult Restart(); void ParseLine(char *line); void ParseLineSegment(char *seg, PRUint32 len); nsresult ParseHead(char *, PRUint32 count, PRUint32 *countRead);