summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol/http/nsHttpTransaction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/protocol/http/nsHttpTransaction.cpp')
-rw-r--r--netwerk/protocol/http/nsHttpTransaction.cpp91
1 files changed, 86 insertions, 5 deletions
diff --git a/netwerk/protocol/http/nsHttpTransaction.cpp b/netwerk/protocol/http/nsHttpTransaction.cpp
index ee3a88489..706710d89 100644
--- a/netwerk/protocol/http/nsHttpTransaction.cpp
+++ b/netwerk/protocol/http/nsHttpTransaction.cpp
@@ -39,6 +39,8 @@
#include "nsIOService.h"
#include "nsIRequestContext.h"
#include "nsIHttpAuthenticator.h"
+#include "NSSErrorsService.h"
+#include "sslerr.h"
#include <algorithm>
#ifdef MOZ_WIDGET_GONK
@@ -144,6 +146,7 @@ nsHttpTransaction::nsHttpTransaction()
, mIsInIsolatedMozBrowser(false)
, mClassOfService(0)
, m0RTTInProgress(false)
+ , mTransportStatus(NS_OK)
{
LOG(("Creating nsHttpTransaction @%p\n", this));
gHttpHandler->GetMaxPipelineObjectSize(&mMaxPipelineObjectSize);
@@ -550,6 +553,50 @@ nsHttpTransaction::OnTransportStatus(nsITransport* transport,
LOG(("nsHttpTransaction::OnSocketStatus [this=%p status=%x progress=%lld]\n",
this, status, progress));
+ // A transaction can given to multiple HalfOpen sockets (this is a bug in
+ // nsHttpConnectionMgr). We are going to fix it here as a work around to be
+ // able to uplift it.
+ switch(status) {
+ case NS_NET_STATUS_RESOLVING_HOST:
+ if (mTransportStatus != NS_OK) {
+ LOG(("nsHttpTransaction::OnSocketStatus - ignore socket events "
+ "from backup transport"));
+ return;
+ }
+ break;
+ case NS_NET_STATUS_RESOLVED_HOST:
+ if (mTransportStatus != NS_NET_STATUS_RESOLVING_HOST &&
+ mTransportStatus != NS_OK) {
+ LOG(("nsHttpTransaction::OnSocketStatus - ignore socket events "
+ "from backup transport"));
+ return;
+ }
+ break;
+ case NS_NET_STATUS_CONNECTING_TO:
+ if (mTransportStatus != NS_NET_STATUS_RESOLVING_HOST &&
+ mTransportStatus != NS_NET_STATUS_RESOLVED_HOST &&
+ mTransportStatus != NS_OK) {
+ LOG(("nsHttpTransaction::OnSocketStatus - ignore socket events "
+ "from backup transport"));
+ return;
+ }
+ break;
+ case NS_NET_STATUS_CONNECTED_TO:
+ if (mTransportStatus != NS_NET_STATUS_RESOLVING_HOST &&
+ mTransportStatus != NS_NET_STATUS_RESOLVED_HOST &&
+ mTransportStatus != NS_NET_STATUS_CONNECTING_TO &&
+ mTransportStatus != NS_OK) {
+ LOG(("nsHttpTransaction::OnSocketStatus - ignore socket events "
+ "from backup transport"));
+ return;
+ }
+ break;
+ default:
+ LOG(("nsHttpTransaction::OnSocketStatus - a new event"));
+ }
+
+ mTransportStatus = status;
+
if (status == NS_NET_STATUS_CONNECTED_TO ||
status == NS_NET_STATUS_WAITING_FOR) {
nsISocketTransport *socketTransport =
@@ -574,7 +621,17 @@ nsHttpTransaction::OnTransportStatus(nsITransport* transport,
} else if (status == NS_NET_STATUS_CONNECTING_TO) {
SetConnectStart(TimeStamp::Now());
} else if (status == NS_NET_STATUS_CONNECTED_TO) {
- SetConnectEnd(TimeStamp::Now());
+ SetConnectEnd(TimeStamp::Now(), true);
+ } else if (status == NS_NET_STATUS_TLS_HANDSHAKE_ENDED) {
+ {
+ // before overwriting connectEnd, copy it to secureConnectionStart
+ MutexAutoLock lock(mLock);
+ if (mTimings.secureConnectionStart.IsNull() &&
+ !mTimings.connectEnd.IsNull()) {
+ mTimings.secureConnectionStart = mTimings.connectEnd;
+ }
+ }
+ SetConnectEnd(TimeStamp::Now(), false);
}
}
@@ -998,7 +1055,9 @@ nsHttpTransaction::Close(nsresult reason)
// connection. It will break that connection and also confuse the channel's
// auth provider, beliving the cached credentials are wrong and asking for
// the password mistakenly again from the user.
- if ((reason == NS_ERROR_NET_RESET || reason == NS_OK) &&
+ if ((reason == NS_ERROR_NET_RESET ||
+ reason == NS_OK ||
+ reason == psm::GetXPCOMFromNSSError(SSL_ERROR_DOWNGRADE_WITH_EARLY_DATA)) &&
(!(mCaps & NS_HTTP_STICKY_CONNECTION) || (mCaps & NS_HTTP_CONNECTION_RESTARTABLE))) {
if (mForceRestart && NS_SUCCEEDED(Restart())) {
@@ -1027,9 +1086,10 @@ nsHttpTransaction::Close(nsresult reason)
bool reallySentData =
mSentData && (!mConnection || mConnection->BytesWritten());
- if (!mReceivedData &&
+ if (reason == psm::GetXPCOMFromNSSError(SSL_ERROR_DOWNGRADE_WITH_EARLY_DATA) ||
+ (!mReceivedData &&
((mRequestHead && mRequestHead->IsSafeMethod()) ||
- !reallySentData || connReused)) {
+ !reallySentData || connReused))) {
// if restarting fails, then we must proceed to close the pipe,
// which will notify the channel that the transaction failed.
@@ -1327,6 +1387,8 @@ nsHttpTransaction::Restart()
}
}
+ mTransportStatus = NS_OK;
+
return gHttpHandler->InitiateTransaction(this, mPriority);
}
@@ -2082,6 +2144,13 @@ nsHttpTransaction::Timings()
}
void
+nsHttpTransaction::BootstrapTimings(TimingStruct times)
+{
+ mozilla::MutexAutoLock lock(mLock);
+ mTimings = times;
+}
+
+void
nsHttpTransaction::SetDomainLookupStart(mozilla::TimeStamp timeStamp, bool onlyIfNull)
{
mozilla::MutexAutoLock lock(mLock);
@@ -2173,6 +2242,13 @@ nsHttpTransaction::GetConnectStart()
}
mozilla::TimeStamp
+nsHttpTransaction::GetSecureConnectionStart()
+{
+ mozilla::MutexAutoLock lock(mLock);
+ return mTimings.secureConnectionStart;
+}
+
+mozilla::TimeStamp
nsHttpTransaction::GetConnectEnd()
{
mozilla::MutexAutoLock lock(mLock);
@@ -2440,8 +2516,9 @@ nsHttpTransaction::Do0RTT()
}
nsresult
-nsHttpTransaction::Finish0RTT(bool aRestart)
+nsHttpTransaction::Finish0RTT(bool aRestart, bool aAlpnChanged /* ignored */)
{
+ LOG(("nsHttpTransaction::Finish0RTT %p %d %d\n", this, aRestart, aAlpnChanged));
MOZ_ASSERT(m0RTTInProgress);
m0RTTInProgress = false;
if (aRestart) {
@@ -2453,6 +2530,10 @@ nsHttpTransaction::Finish0RTT(bool aRestart)
} else {
return NS_ERROR_FAILURE;
}
+ } else if (!mConnected) {
+ // this is code that was skipped in ::ReadSegments while in 0RTT
+ mConnected = true;
+ mConnection->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
}
return NS_OK;
}