Bug 1003320 - Send HPACK buffer size updates when receiving SETTINGS_HEADER_TABLE_SIZE. r=mcmanus
authorNicholas Hurley <hurley@todesschaf.org>
Tue, 29 Apr 2014 18:46:07 -0700
changeset 181289 68e78cfc9094234eb3733e715a52995713a2b67e
parent 181288 b5e2228862e84b2c6437ed478648ab157434326b
child 181290 24dedc2a7064523474d2d61153e3d9713fa2730c
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersmcmanus
bugs1003320
milestone32.0a1
Bug 1003320 - Send HPACK buffer size updates when receiving SETTINGS_HEADER_TABLE_SIZE. r=mcmanus
netwerk/protocol/http/Http2Compression.cpp
netwerk/protocol/http/Http2Compression.h
--- a/netwerk/protocol/http/Http2Compression.cpp
+++ b/netwerk/protocol/http/Http2Compression.cpp
@@ -902,16 +902,25 @@ Http2Compressor::EncodeHeaderBlock(const
 {
   mAlternateReferenceSet.Clear();
   mImpliedReferenceSet.Clear();
   mOutput = &output;
   output.SetCapacity(1024);
   output.Truncate();
   mParsedContentLength = -1;
 
+  // first thing's first - context size updates (if necessary)
+  if (mBufferSizeChangeWaiting) {
+    if (mLowestBufferSizeWaiting < mMaxBufferSetting) {
+      EncodeTableSizeChange(mLowestBufferSizeWaiting);
+    }
+    EncodeTableSizeChange(mMaxBufferSetting);
+    mBufferSizeChangeWaiting = false;
+  }
+
   // colon headers first
   ProcessHeader(nvPair(NS_LITERAL_CSTRING(":method"), method), false);
   ProcessHeader(nvPair(NS_LITERAL_CSTRING(":path"), path), false);
   ProcessHeader(nvPair(NS_LITERAL_CSTRING(":authority"), host), false);
   ProcessHeader(nvPair(NS_LITERAL_CSTRING(":scheme"), scheme), false);
 
   // now the non colon headers
   const char *beginBuffer = nvInput.BeginReading();
@@ -1382,20 +1391,35 @@ Http2Compressor::ProcessHeader(const nvP
     mAlternateReferenceSet.AppendElement(0);
   } else {
     mAlternateReferenceSet.AppendElement(matchedIndex);
   }
   return;
 }
 
 void
+Http2Compressor::EncodeTableSizeChange(uint32_t newMaxSize)
+{
+  uint32_t offset = mOutput->Length();
+  EncodeInteger(4, newMaxSize);
+  uint8_t *startByte = reinterpret_cast<uint8_t *>(mOutput->BeginWriting()) + offset;
+  *startByte = *startByte | 0x20;
+}
+
+void
 Http2Compressor::SetMaxBufferSize(uint32_t maxBufferSize)
 {
   mMaxBufferSetting = maxBufferSize;
   SetMaxBufferSizeInternal(maxBufferSize);
+  if (!mBufferSizeChangeWaiting) {
+    mBufferSizeChangeWaiting = true;
+    mLowestBufferSizeWaiting = maxBufferSize;
+  } else if (maxBufferSize < mLowestBufferSizeWaiting) {
+    mLowestBufferSizeWaiting = maxBufferSize;
+  }
 }
 
 nsresult
 Http2Compressor::SetMaxBufferSizeInternal(uint32_t maxBufferSize)
 {
   if (maxBufferSize > mMaxBufferSetting) {
     return NS_ERROR_ILLEGAL_VALUE;
   }
--- a/netwerk/protocol/http/Http2Compression.h
+++ b/netwerk/protocol/http/Http2Compression.h
@@ -147,17 +147,21 @@ private:
   const uint8_t *mData;
   uint32_t mDataLen;
 };
 
 
 class Http2Compressor MOZ_FINAL : public Http2BaseCompressor
 {
 public:
-  Http2Compressor() : mParsedContentLength(-1) { };
+  Http2Compressor() : mParsedContentLength(-1),
+                      mMaxBufferSetting(kDefaultMaxBuffer),
+                      mBufferSizeChangeWaiting(false),
+                      mLowestBufferSizeWaiting(0)
+  { };
   virtual ~Http2Compressor() { }
 
   // HTTP/1 formatted header block as input - HTTP/2 formatted
   // header block as output
   nsresult EncodeHeaderBlock(const nsCString &nvInput,
                              const nsACString &method, const nsACString &path,
                              const nsACString &host, const nsACString &scheme,
                              nsACString &output);
@@ -183,19 +187,22 @@ private:
     kNop
   };
 
   void DoOutput(Http2Compressor::outputCode code,
                 const class nvPair *pair, uint32_t index);
   void EncodeInteger(uint32_t prefixLen, uint32_t val);
   void ProcessHeader(const nvPair inputPair, bool neverIndex);
   void HuffmanAppend(const nsCString &value);
+  void EncodeTableSizeChange(uint32_t newMaxSize);
 
   int64_t mParsedContentLength;
   uint32_t mMaxBufferSetting;
+  bool mBufferSizeChangeWaiting;
+  uint32_t mLowestBufferSizeWaiting;
 
   nsAutoTArray<uint32_t, 64> mImpliedReferenceSet;
 };
 
 } // namespace mozilla::net
 } // namespace mozilla
 
 #endif // mozilla_net_Http2Compression_Internal_h