bug 1208114 - fix h2 connect tunnels r=hurley
☠☠ backed out by 0b1fbd9ec549 ☠ ☠
authorPatrick McManus <mcmanus@ducksong.com>
Wed, 07 Oct 2015 12:55:07 -0400
changeset 266870 3cd86929d8835f2b162dc2c8654ae9af2a54e06f
parent 266869 f2f0e5491de5472f1ec4f1a744e48bbc946ab2d8
child 266871 f627ad014e6c30a0a3fd0f00210107ae78e7ab1d
push id66318
push usermcmanus@ducksong.com
push dateThu, 08 Oct 2015 19:01:17 +0000
treeherdermozilla-inbound@3cd86929d883 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershurley
bugs1208114
milestone44.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 1208114 - fix h2 connect tunnels r=hurley
netwerk/protocol/http/Http2Session.cpp
netwerk/protocol/http/Http2Stream.cpp
netwerk/protocol/http/TunnelUtils.cpp
netwerk/protocol/http/TunnelUtils.h
--- a/netwerk/protocol/http/Http2Session.cpp
+++ b/netwerk/protocol/http/Http2Session.cpp
@@ -3184,17 +3184,18 @@ Http2Session::OnWriteSegment(char *buf,
   nsresult rv;
 
   if (!mSegmentWriter) {
     // the only way this could happen would be if Close() were called on the
     // stack with WriteSegments()
     return NS_ERROR_FAILURE;
   }
 
-  if (mDownstreamState == NOT_USING_NETWORK) {
+  if (mDownstreamState == NOT_USING_NETWORK ||
+      mDownstreamState == BUFFERING_FRAME_HEADER) {
     return NS_BASE_STREAM_WOULD_BLOCK;
   }
 
   if (mDownstreamState == PROCESSING_DATA_FRAME) {
 
     if (mInputFrameFinal &&
         mInputFrameDataRead == mInputFrameDataSize) {
       *countWritten = 0;
@@ -3266,16 +3267,17 @@ Http2Session::OnWriteSegment(char *buf,
         // cleanup the stream.
         ResetDownstreamState();
       }
     }
 
     return NS_OK;
   }
 
+  MOZ_ASSERT(false);
   return NS_ERROR_UNEXPECTED;
 }
 
 void
 Http2Session::SetNeedsCleanup()
 {
   LOG3(("Http2Session::SetNeedsCleanup %p - recorded downstream fin of "
         "stream %p 0x%X", this, mInputFrameDataStream,
--- a/netwerk/protocol/http/Http2Stream.cpp
+++ b/netwerk/protocol/http/Http2Stream.cpp
@@ -319,18 +319,30 @@ Http2Stream::WriteSegments(nsAHttpSegmen
   mSegmentWriter = writer;
   nsresult rv = mTransaction->WriteSegments(this, count, countWritten);
 
   if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
     // consuming transaction won't take data. but we need to read it into a buffer so that it
     // won't block other streams. but we should not advance the flow control window
     // so that we'll eventually push back on the sender.
 
+    // with tunnels you need to make sure that this is an underlying connction established
+    // that can be meaningfully giving this signal
+    bool doBuffer = true;
+    if (mIsTunnel) {
+      nsRefPtr<SpdyConnectTransaction> qiTrans(mTransaction->QuerySpdyConnectTransaction());
+      if (qiTrans) {
+        doBuffer = qiTrans->ConnectedReadyForInput();
+      }
+    }
     // stash this data
-    rv = BufferInput(count, countWritten);
+    if (doBuffer) {
+      rv = BufferInput(count, countWritten);
+      LOG3(("Http2Stream::WriteSegments %p Buffered %X %d\n", this, rv, *countWritten));
+    }
   }
   mSegmentWriter = nullptr;
   return rv;
 }
 
 nsresult
 Http2Stream::MakeOriginURL(const nsACString &origin, nsRefPtr<nsStandardURL> &url)
 {
--- a/netwerk/protocol/http/TunnelUtils.cpp
+++ b/netwerk/protocol/http/TunnelUtils.cpp
@@ -1258,16 +1258,22 @@ SpdyConnectTransaction::WriteSegments(ns
        "goodput %p out %llu\n", this, mTunneledConn.get(),
        mTunneledConn->ContentBytesWritten()));
   if (NS_SUCCEEDED(rv) && !mTunneledConn->ContentBytesWritten()) {
     mTunnelStreamOut->AsyncWait(mTunnelStreamOut->mCallback, 0, 0, nullptr);
   }
   return rv;
 }
 
+bool
+SpdyConnectTransaction::ConnectedReadyForInput()
+{
+  return mTunneledConn && mTunnelStreamIn->mCallback;
+}
+
 nsHttpRequestHead *
 SpdyConnectTransaction::RequestHead()
 {
   return mRequestHead;
 }
 
 void
 SpdyConnectTransaction::Close(nsresult code)
--- a/netwerk/protocol/http/TunnelUtils.h
+++ b/netwerk/protocol/http/TunnelUtils.h
@@ -196,16 +196,20 @@ public:
 
   nsresult ReadSegments(nsAHttpSegmentReader *reader,
                         uint32_t count, uint32_t *countRead) override final;
   nsresult WriteSegments(nsAHttpSegmentWriter *writer,
                          uint32_t count, uint32_t *countWritten) override final;
   nsHttpRequestHead *RequestHead() override final;
   void Close(nsresult reason) override final;
 
+  // ConnectedReadyForInput() tests whether the spdy connect transaction is attached to
+  // an nsHttpConnection that can properly deal with flow control, etc..
+  bool ConnectedReadyForInput();
+
 private:
   friend class InputStreamShim;
   friend class OutputStreamShim;
 
   nsresult Flush(uint32_t count, uint32_t *countRead);
   void CreateShimError(nsresult code);
 
   nsCString             mConnectString;