tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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