Bug 1409858 - H2 CONNECT Tunnel Marked Plaintext Too Late r=nwgh draft
authorPatrick McManus <mcmanus@ducksong.com>
Fri, 20 Oct 2017 13:39:49 -0400
changeset 686819 b71e73e7a9e3e4468154a3a073b62fd5e7fe3f69
parent 683863 d1e995c8640a191cd127e87273ec96cb2fabffa9
child 737484 500e0ab4cfb6a571c68be98bebb8ef11b505ab07
push id86305
push userbmo:mcmanus@ducksong.com
push dateThu, 26 Oct 2017 13:19:20 +0000
reviewersnwgh
bugs1409858
milestone58.0a1
Bug 1409858 - H2 CONNECT Tunnel Marked Plaintext Too Late r=nwgh MozReview-Commit-ID: IjuYDuvufRd
netwerk/protocol/http/Http2Session.cpp
netwerk/protocol/http/Http2Stream.cpp
netwerk/protocol/http/TunnelUtils.cpp
--- a/netwerk/protocol/http/Http2Session.cpp
+++ b/netwerk/protocol/http/Http2Session.cpp
@@ -590,19 +590,28 @@ Http2Session::FlushOutputQueue()
     RealignOutputQueue();
   }
 }
 
 void
 Http2Session::DontReuse()
 {
   LOG3(("Http2Session::DontReuse %p\n", this));
+  if (!OnSocketThread()) {
+    LOG3(("Http2Session %p not on socket thread\n", this));
+    nsCOMPtr<nsIRunnable> event = NewRunnableMethod(
+      "Http2Session::DontReuse", this, &Http2Session::DontReuse);
+    gSocketTransportService->Dispatch(event, NS_DISPATCH_NORMAL);
+    return;
+  }
+
   mShouldGoAway = true;
-  if (!mStreamTransactionHash.Count())
+  if (!mClosed && !mStreamTransactionHash.Count()) {
     Close(NS_OK);
+  }
 }
 
 uint32_t
 Http2Session::SpdyVersion()
 {
   return HTTP_VERSION_2;
 }
 
--- a/netwerk/protocol/http/Http2Stream.cpp
+++ b/netwerk/protocol/http/Http2Stream.cpp
@@ -1047,16 +1047,18 @@ Http2Stream::ConvertResponseHeaders(Http
   }
 
   LOG3(("Http2Stream::ConvertResponseHeaders %p response code %d\n", this, httpResponseCode));
   if (mIsTunnel) {
     LOG3(("Http2Stream %p Tunnel Response code %d", this, httpResponseCode));
     if ((httpResponseCode / 100) != 2) {
       MapStreamToPlainText();
     }
+    MapStreamToHttpConnection();
+    ClearTransactionsBlockedOnTunnel();
   }
 
   if (httpResponseCode == 101) {
     // 8.1.1 of h2 disallows 101.. throw PROTOCOL_ERROR on stream
     LOG3(("Http2Stream::ConvertResponseHeaders %p Error - status == 101\n", this));
     return NS_ERROR_ILLEGAL_VALUE;
   }
 
@@ -1156,20 +1158,16 @@ Http2Stream::SetAllHeadersReceived()
     // pushed streams needs to wait until headers have
     // arrived to open up their window
     LOG3(("Http2Stream::SetAllHeadersReceived %p state OPEN from reserved\n", this));
     mState = OPEN;
     AdjustInitialWindow();
   }
 
   mAllHeadersReceived = 1;
-  if (mIsTunnel) {
-    MapStreamToHttpConnection();
-    ClearTransactionsBlockedOnTunnel();
-  }
 }
 
 bool
 Http2Stream::AllowFlowControlledWrite()
 {
   return (mSession->ServerSessionWindow() > 0) && (mServerReceiveWindow > 0);
 }
 
--- a/netwerk/protocol/http/TunnelUtils.cpp
+++ b/netwerk/protocol/http/TunnelUtils.cpp
@@ -387,24 +387,25 @@ TLSFilterTransaction::NudgeTunnel(NudgeT
   MOZ_ASSERT(OnSocketThread(), "not on socket thread");
   LOG(("TLSFilterTransaction %p NudgeTunnel\n", this));
   mNudgeCallback = nullptr;
 
   if (!mSecInfo) {
     return NS_ERROR_FAILURE;
   }
 
-  uint32_t notUsed;
-  int32_t written = PR_Write(mFD, "", 0);
-  if ((written < 0) && (PR_GetError() != PR_WOULD_BLOCK_ERROR)) {
+  nsCOMPtr<nsISSLSocketControl> ssl(do_QueryInterface(mSecInfo));
+  nsresult rv = ssl ? ssl->DriveHandshake() : NS_ERROR_FAILURE;
+  if (NS_FAILED(rv) && rv != NS_BASE_STREAM_WOULD_BLOCK) {
     // fatal handshake failure
     LOG(("TLSFilterTransaction %p Fatal Handshake Failure: %d\n", this, PR_GetError()));
     return NS_ERROR_FAILURE;
   }
 
+  uint32_t notUsed;
   Unused << OnReadSegment("", 0, &notUsed);
 
   // The SSL Layer does some unusual things with PR_Poll that makes it a bad
   // match for multiplexed SSL sessions. We work around this by manually polling for
   // the moment during the brief handshake phase or otherwise blocked on write.
   // Thankfully this is a pretty unusual state. NSPR doesn't help us here -
   // asserting when polling without the NSPR IO layer on the bottom of
   // the stack. As a follow-on we can do some NSPR and maybe libssl changes