bug 1208114 - fix h2 connect tunnels r=hurley
authorPatrick McManus <mcmanus@ducksong.com>
Wed, 07 Oct 2015 12:55:07 -0400
changeset 300378 c66bf1d6890b605846f5a3dd49d7e1aad4563bbb
parent 300377 71882ec538cd0371797d4ed1e30e58f240dad973
child 300379 b07364d8053fd8ab7af61fd16e44e48a4250f023
push id5392
push userraliiev@mozilla.com
push dateMon, 14 Dec 2015 20:08:23 +0000
treeherdermozilla-beta@16ce8562a975 [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
@@ -3187,17 +3187,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;
--- 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;