bug 1012825 - https proxying over http/2 connect stream r=hurley
authorPatrick McManus <mcmanus@ducksong.com>
Mon, 19 May 2014 15:37:35 -0400
changeset 184020 1950bbf9626c083c5869e711ad4e513322f31003
parent 184019 4b51ac1ac79e6cdcfcb7b577f60ac4640720fb34
child 184021 94e3479f64ab3d751ad05b83b7810fd391cc1dd6
push id26810
push usercbook@mozilla.com
push dateWed, 21 May 2014 11:46:36 +0000
treeherdermozilla-central@50fb8c4db2fd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershurley
bugs1012825
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 1012825 - https proxying over http/2 connect stream r=hurley
netwerk/protocol/http/Http2Session.cpp
netwerk/protocol/http/Http2Stream.cpp
netwerk/protocol/http/Http2Stream.h
netwerk/protocol/http/TunnelUtils.cpp
netwerk/protocol/http/TunnelUtils.h
--- a/netwerk/protocol/http/Http2Session.cpp
+++ b/netwerk/protocol/http/Http2Session.cpp
@@ -1137,43 +1137,39 @@ nsresult
 Http2Session::ResponseHeadersComplete()
 {
   LOG3(("Http2Session::ResponseHeadersComplete %p for 0x%X fin=%d",
         this, mInputFrameDataStream->StreamID(), mInputFrameFinal));
 
   // only do this once, afterwards ignore trailers
   if (mInputFrameDataStream->AllHeadersReceived())
     return NS_OK;
-  nsresult rv = mInputFrameDataStream->SetAllHeadersReceived(true);
-
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
+  mInputFrameDataStream->SetAllHeadersReceived();
 
   // The stream needs to see flattened http headers
   // Uncompressed http/2 format headers currently live in
   // Http2Stream::mDecompressBuffer - convert that to HTTP format in
   // mFlatHTTPResponseHeaders via ConvertHeaders()
 
+  nsresult rv;
   mFlatHTTPResponseHeadersOut = 0;
   rv = mInputFrameDataStream->ConvertResponseHeaders(&mDecompressor,
                                                      mDecompressBuffer,
                                                      mFlatHTTPResponseHeaders);
   if (rv == NS_ERROR_ABORT) {
     LOG(("Http2Session::ResponseHeadersComplete ConvertResponseHeaders aborted\n"));
     if (mInputFrameDataStream->IsTunnel()) {
       gHttpHandler->ConnMgr()->CancelTransactions(
         mInputFrameDataStream->Transaction()->ConnectionInfo(),
         NS_ERROR_CONNECTION_REFUSED);
     }
     CleanupStream(mInputFrameDataStream, rv, CANCEL_ERROR);
     ResetDownstreamState();
     return NS_OK;
-  }
-  else if (NS_FAILED(rv)) {
+  } else if (NS_FAILED(rv)) {
     return rv;
   }
 
   ChangeDownstreamState(PROCESSING_COMPLETE_HEADERS);
   return NS_OK;
 }
 
 nsresult
--- a/netwerk/protocol/http/Http2Stream.cpp
+++ b/netwerk/protocol/http/Http2Stream.cpp
@@ -928,21 +928,29 @@ Http2Stream::ConvertPushHeaders(Http2Dec
 }
 
 void
 Http2Stream::Close(nsresult reason)
 {
   mTransaction->Close(reason);
 }
 
-nsresult
-Http2Stream::SetAllHeadersReceived(bool aStatus)
+void
+Http2Stream::SetAllHeadersReceived()
 {
-  mAllHeadersReceived = aStatus ? 1 : 0;
-  return NS_OK;
+  if (mAllHeadersReceived) {
+    return;
+  }
+
+  mAllHeadersReceived = 1;
+  if (mIsTunnel) {
+    MapStreamToHttpConnection();
+    ClearTransactionsBlockedOnTunnel();
+  }
+  return;
 }
 
 bool
 Http2Stream::AllowFlowControlledWrite()
 {
   return (mSession->ServerSessionWindow() > 0) && (mServerReceiveWindow > 0);
 }
 
--- a/netwerk/protocol/http/Http2Stream.h
+++ b/netwerk/protocol/http/Http2Stream.h
@@ -76,19 +76,17 @@ public:
   bool RecvdReset() { return mRecvdReset; }
 
   void SetSentReset(bool aStatus);
   bool SentReset() { return mSentReset; }
 
   void SetCountAsActive(bool aStatus) { mCountAsActive = aStatus ? 1 : 0; }
   bool CountAsActive() { return mCountAsActive; }
 
- // returns failure if stream cannot be made ready and stream
- // should be canceled
-  nsresult SetAllHeadersReceived(bool aStatus);
+  void SetAllHeadersReceived();
   bool AllHeadersReceived() { return mAllHeadersReceived; }
 
   void UpdateTransportSendEvents(uint32_t count);
   void UpdateTransportReadEvents(uint32_t count);
 
   // NS_ERROR_ABORT terminates stream, other failure terminates session
   nsresult ConvertResponseHeaders(Http2Decompressor *, nsACString &, nsACString &);
   nsresult ConvertPushHeaders(Http2Decompressor *, nsACString &, nsACString &);
--- a/netwerk/protocol/http/TunnelUtils.cpp
+++ b/netwerk/protocol/http/TunnelUtils.cpp
@@ -927,17 +927,17 @@ SpdyConnectTransaction::CreateShimError(
 
 nsresult
 SpdyConnectTransaction::WriteSegments(nsAHttpSegmentWriter *writer,
                                       uint32_t count,
                                       uint32_t *countWritten)
 {
   MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
   LOG(("SpdyConnectTransaction::WriteSegments %p max=%d cb=%p\n",
-       this, count, mTunnelStreamIn->mCallback));
+       this, count, mTunneledConn ? mTunnelStreamIn->mCallback : nullptr));
 
   // first call into the tunnel stream to get the demux'd data out of the
   // spdy session.
   EnsureBuffer(mInputData, mInputDataUsed + count, mInputDataUsed, mInputDataSize);
   nsresult rv = writer->OnWriteSegment(mInputData + mInputDataUsed,
                                        count, countWritten);
   if (NS_FAILED(rv)) {
     if (rv != NS_BASE_STREAM_WOULD_BLOCK) {
@@ -945,17 +945,17 @@ SpdyConnectTransaction::WriteSegments(ns
       CreateShimError(rv);
     }
     return rv;
   }
   mInputDataUsed += *countWritten;
   LOG(("SpdyConnectTransaction %p %d new bytes [%d total] of ciphered data buffered\n",
        this, *countWritten, mInputDataUsed - mInputDataOffset));
 
-  if (!mTunnelStreamIn->mCallback) {
+  if (!mTunneledConn || !mTunnelStreamIn->mCallback) {
     return NS_BASE_STREAM_WOULD_BLOCK;
   }
 
   rv = mTunnelStreamIn->mCallback->OnInputStreamReady(mTunnelStreamIn);
   LOG(("SpdyConnectTransaction::WriteSegments %p "
        "after InputStreamReady callback %d total of ciphered data buffered rv=%x\n",
        this, mInputDataUsed - mInputDataOffset, rv));
   LOG(("SpdyConnectTransaction::WriteSegments %p "
--- a/netwerk/protocol/http/TunnelUtils.h
+++ b/netwerk/protocol/http/TunnelUtils.h
@@ -204,18 +204,23 @@ private:
   uint32_t             mInputDataOffset;
 
   nsAutoArrayPtr<char> mOutputData;
   uint32_t             mOutputDataSize;
   uint32_t             mOutputDataUsed;
   uint32_t             mOutputDataOffset;
 
   TimeStamp                      mTimestampSyn;
+  nsRefPtr<nsHttpConnectionInfo> mConnInfo;
+
+  // mTunneledConn, mTunnelTransport, mTunnelStreamIn, mTunnelStreamOut
+  // are the connectors to the "real" http connection. They are created
+  // together when the tunnel setup is complete and a static reference is held
+  // for the lifetime of the tunnel.
   nsRefPtr<nsHttpConnection>     mTunneledConn;
-  nsRefPtr<nsHttpConnectionInfo> mConnInfo;
   nsRefPtr<SocketTransportShim>  mTunnelTransport;
   nsRefPtr<InputStreamShim>      mTunnelStreamIn;
   nsRefPtr<OutputStreamShim>     mTunnelStreamOut;
 };
 
 }} // namespace mozilla::net
 
 #endif // mozilla_net_TLSFilterTransaction_h