Http2Compression.h (6459B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef mozilla_net_Http2Compression_Internal_h 7 #define mozilla_net_Http2Compression_Internal_h 8 9 // HPACK - RFC 7541 10 // https://www.rfc-editor.org/rfc/rfc7541.txt 11 12 #include "mozilla/Attributes.h" 13 #include "nsDeque.h" 14 #include "nsString.h" 15 #include "mozilla/Mutex.h" 16 17 namespace mozilla { 18 namespace net { 19 20 struct HuffmanIncomingTable; 21 22 void Http2CompressionCleanup(); 23 24 class nvPair { 25 public: 26 nvPair(const nsACString& name, const nsACString& value) 27 : mName(name), mValue(value) {} 28 29 uint32_t Size() const { return mName.Length() + mValue.Length() + 32; } 30 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const; 31 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const; 32 33 nsCString mName; 34 nsCString mValue; 35 }; 36 37 class nvFIFO { 38 public: 39 nvFIFO(); 40 ~nvFIFO(); 41 void AddElement(const nsCString& name, const nsCString& value); 42 void AddElement(const nsCString& name); 43 void RemoveElement(); 44 uint32_t ByteCount() const; 45 uint32_t Length() const; 46 uint32_t VariableLength() const; 47 size_t StaticLength() const; 48 void Clear(); 49 const nvPair* operator[](size_t index) const; 50 size_t SizeOfDynamicTable(mozilla::MallocSizeOf aMallocSizeOf) const; 51 52 private: 53 uint32_t mByteCount{0}; 54 nsDeque<nvPair> mTable; 55 56 // This mutex is held when adding or removing elements in the table 57 // and when accessing the table from the main thread (in SizeOfDynamicTable) 58 // Since the operator[] and other const methods are always called 59 // on the socket thread, they don't need to lock the mutex. 60 // Mutable so it can be locked in SizeOfDynamicTable which is const 61 mutable Mutex mMutex MOZ_UNANNOTATED{"nvFIFO"}; 62 }; 63 64 class HpackDynamicTableReporter; 65 66 class Http2BaseCompressor { 67 public: 68 Http2BaseCompressor(); 69 virtual ~Http2BaseCompressor(); 70 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 71 nsresult SetInitialMaxBufferSize(uint32_t maxBufferSize); 72 void SetDumpTables(bool dumpTables); 73 74 protected: 75 const static uint32_t kDefaultMaxBuffer = 4096; 76 77 virtual void ClearHeaderTable(); 78 virtual void MakeRoom(uint32_t amount, const char* direction); 79 virtual void DumpState(const char*); 80 virtual void SetMaxBufferSizeInternal(uint32_t maxBufferSize); 81 82 nsACString* mOutput{nullptr}; 83 nvFIFO mHeaderTable; 84 85 uint32_t mMaxBuffer{kDefaultMaxBuffer}; 86 uint32_t mMaxBufferSetting{kDefaultMaxBuffer}; 87 bool mSetInitialMaxBufferSizeAllowed{true}; 88 89 uint32_t mPeakSize{0}; 90 uint32_t mPeakCount{0}; 91 92 bool mDumpTables{false}; 93 94 private: 95 RefPtr<HpackDynamicTableReporter> mDynamicReporter; 96 }; 97 98 class Http2Compressor; 99 100 class Http2Decompressor final : public Http2BaseCompressor { 101 public: 102 Http2Decompressor() = default; 103 virtual ~Http2Decompressor(); 104 105 // NS_OK: Produces the working set of HTTP/1 formatted headers 106 [[nodiscard]] nsresult DecodeHeaderBlock(const uint8_t* data, 107 uint32_t datalen, nsACString& output, 108 bool isPush); 109 110 void GetStatus(nsACString& hdr) { hdr = mHeaderStatus; } 111 void GetHost(nsACString& hdr) { hdr = mHeaderHost; } 112 void GetScheme(nsACString& hdr) { hdr = mHeaderScheme; } 113 void GetPath(nsACString& hdr) { hdr = mHeaderPath; } 114 void GetMethod(nsACString& hdr) { hdr = mHeaderMethod; } 115 116 private: 117 [[nodiscard]] nsresult DoIndexed(); 118 [[nodiscard]] nsresult DoLiteralWithoutIndex(); 119 [[nodiscard]] nsresult DoLiteralWithIncremental(); 120 [[nodiscard]] nsresult DoLiteralInternal(nsACString&, nsACString&, uint32_t); 121 [[nodiscard]] nsresult DoLiteralNeverIndexed(); 122 [[nodiscard]] nsresult DoContextUpdate(); 123 124 [[nodiscard]] nsresult DecodeInteger(uint32_t prefixLen, uint32_t& accum); 125 [[nodiscard]] nsresult OutputHeader(uint32_t index); 126 [[nodiscard]] nsresult OutputHeader(const nsACString& name, 127 const nsACString& value); 128 129 [[nodiscard]] nsresult CopyHeaderString(uint32_t index, nsACString& name); 130 [[nodiscard]] nsresult CopyStringFromInput(uint32_t bytes, nsACString& val); 131 uint8_t ExtractByte(uint8_t bitsLeft, uint32_t& bytesConsumed); 132 [[nodiscard]] nsresult CopyHuffmanStringFromInput(uint32_t bytes, 133 nsACString& val); 134 [[nodiscard]] nsresult DecodeHuffmanCharacter( 135 const HuffmanIncomingTable* table, uint8_t& c, uint32_t& bytesConsumed, 136 uint8_t& bitsLeft); 137 [[nodiscard]] nsresult DecodeFinalHuffmanCharacter( 138 const HuffmanIncomingTable* table, uint8_t& c, uint8_t& bitsLeft); 139 140 nsCString mHeaderStatus; 141 nsCString mHeaderHost; 142 nsCString mHeaderScheme; 143 nsCString mHeaderPath; 144 nsCString mHeaderMethod; 145 146 // state variables when DecodeBlock() is on the stack 147 uint32_t mOffset{0}; 148 const uint8_t* mData{nullptr}; 149 uint32_t mDataLen{0}; 150 bool mSeenNonColonHeader{false}; 151 bool mIsPush{false}; 152 }; 153 154 class Http2Compressor final : public Http2BaseCompressor { 155 public: 156 Http2Compressor() = default; 157 virtual ~Http2Compressor(); 158 159 // HTTP/1 formatted header block as input - HTTP/2 formatted 160 // header block as output 161 [[nodiscard]] nsresult EncodeHeaderBlock( 162 const nsCString& nvInput, const nsACString& method, 163 const nsACString& path, const nsACString& host, const nsACString& scheme, 164 const nsACString& protocol, bool simpleConnectForm, nsACString& output, 165 bool addTEHeader); 166 167 int64_t GetParsedContentLength() { 168 return mParsedContentLength; 169 } // -1 on not found 170 171 void SetMaxBufferSize(uint32_t maxBufferSize); 172 173 private: 174 enum outputCode { 175 kNeverIndexedLiteral, 176 kPlainLiteral, 177 kIndexedLiteral, 178 kIndex 179 }; 180 181 void DoOutput(Http2Compressor::outputCode code, const class nvPair* pair, 182 uint32_t index); 183 void EncodeInteger(uint32_t prefixLen, uint32_t val); 184 void ProcessHeader(const nvPair inputPair, bool noLocalIndex, 185 bool neverIndex); 186 void HuffmanAppend(const nsCString& value); 187 void EncodeTableSizeChange(uint32_t newMaxSize); 188 189 int64_t mParsedContentLength{-1}; 190 bool mBufferSizeChangeWaiting{false}; 191 uint32_t mLowestBufferSizeWaiting{0}; 192 }; 193 194 } // namespace net 195 } // namespace mozilla 196 197 #endif // mozilla_net_Http2Compression_Internal_h