Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/netwerk/protocol/http/Http2Compression.h
Line
Count
Source (jump to first uncovered line)
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 "nsIMemoryReporter.h"
16
#include "mozilla/Telemetry.h"
17
18
namespace mozilla {
19
namespace net {
20
21
struct HuffmanIncomingTable;
22
23
void Http2CompressionCleanup();
24
25
class nvPair
26
{
27
public:
28
nvPair(const nsACString &name, const nsACString &value)
29
  : mName(name)
30
  , mValue(value)
31
0
  { }
32
33
0
  uint32_t Size() const { return mName.Length() + mValue.Length() + 32; }
34
  size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
35
  size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
36
37
  nsCString mName;
38
  nsCString mValue;
39
};
40
41
class nvFIFO
42
{
43
public:
44
  nvFIFO();
45
  ~nvFIFO();
46
  void AddElement(const nsCString &name, const nsCString &value);
47
  void AddElement(const nsCString &name);
48
  void RemoveElement();
49
  uint32_t ByteCount() const;
50
  uint32_t Length() const;
51
  uint32_t VariableLength() const;
52
  size_t StaticLength() const;
53
  void Clear();
54
  const nvPair *operator[] (size_t index) const;
55
56
private:
57
  uint32_t mByteCount;
58
  nsDeque  mTable;
59
};
60
61
class HpackDynamicTableReporter;
62
63
class Http2BaseCompressor
64
{
65
public:
66
  Http2BaseCompressor();
67
  virtual ~Http2BaseCompressor();
68
  size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
69
  nsresult SetInitialMaxBufferSize(uint32_t maxBufferSize);
70
71
protected:
72
  const static uint32_t kDefaultMaxBuffer = 4096;
73
74
  virtual void ClearHeaderTable();
75
  virtual void MakeRoom(uint32_t amount, const char *direction);
76
  virtual void DumpState();
77
  virtual void SetMaxBufferSizeInternal(uint32_t maxBufferSize);
78
79
  nsACString *mOutput;
80
  nvFIFO mHeaderTable;
81
82
  uint32_t mMaxBuffer;
83
  uint32_t mMaxBufferSetting;
84
  bool mSetInitialMaxBufferSizeAllowed;
85
86
  uint32_t mPeakSize;
87
  uint32_t mPeakCount;
88
  MOZ_INIT_OUTSIDE_CTOR
89
  Telemetry::HistogramID mPeakSizeID;
90
  MOZ_INIT_OUTSIDE_CTOR
91
  Telemetry::HistogramID mPeakCountID;
92
93
private:
94
  RefPtr<HpackDynamicTableReporter> mDynamicReporter;
95
};
96
97
class Http2Compressor;
98
99
class Http2Decompressor final : public Http2BaseCompressor
100
{
101
public:
102
  Http2Decompressor()
103
    : mOffset(0)
104
    , mData(nullptr)
105
    , mDataLen(0)
106
    , mSeenNonColonHeader(false)
107
    , mIsPush(false)
108
0
  {
109
0
    mPeakSizeID = Telemetry::HPACK_PEAK_SIZE_DECOMPRESSOR;
110
0
    mPeakCountID = Telemetry::HPACK_PEAK_COUNT_DECOMPRESSOR;
111
0
  };
112
0
  virtual ~Http2Decompressor() = default;
113
114
  // NS_OK: Produces the working set of HTTP/1 formatted headers
115
  MOZ_MUST_USE nsresult DecodeHeaderBlock(const uint8_t *data,
116
                                          uint32_t datalen, nsACString &output,
117
                                          bool isPush);
118
119
0
  void GetStatus(nsACString &hdr) { hdr = mHeaderStatus; }
120
0
  void GetHost(nsACString &hdr) { hdr = mHeaderHost; }
121
0
  void GetScheme(nsACString &hdr) { hdr = mHeaderScheme; }
122
0
  void GetPath(nsACString &hdr) { hdr = mHeaderPath; }
123
0
  void GetMethod(nsACString &hdr) { hdr = mHeaderMethod; }
124
125
private:
126
  MOZ_MUST_USE nsresult DoIndexed();
127
  MOZ_MUST_USE nsresult DoLiteralWithoutIndex();
128
  MOZ_MUST_USE nsresult DoLiteralWithIncremental();
129
  MOZ_MUST_USE nsresult DoLiteralInternal(nsACString &, nsACString &, uint32_t);
130
  MOZ_MUST_USE nsresult DoLiteralNeverIndexed();
131
  MOZ_MUST_USE nsresult DoContextUpdate();
132
133
  MOZ_MUST_USE nsresult DecodeInteger(uint32_t prefixLen, uint32_t &result);
134
  MOZ_MUST_USE nsresult OutputHeader(uint32_t index);
135
  MOZ_MUST_USE nsresult OutputHeader(const nsACString &name, const nsACString &value);
136
137
  MOZ_MUST_USE nsresult CopyHeaderString(uint32_t index, nsACString &name);
138
  MOZ_MUST_USE nsresult CopyStringFromInput(uint32_t index, nsACString &val);
139
  uint8_t ExtractByte(uint8_t bitsLeft, uint32_t &bytesConsumed);
140
  MOZ_MUST_USE nsresult CopyHuffmanStringFromInput(uint32_t index, nsACString &val);
141
  MOZ_MUST_USE nsresult
142
  DecodeHuffmanCharacter(const HuffmanIncomingTable *table, uint8_t &c,
143
                         uint32_t &bytesConsumed, uint8_t &bitsLeft);
144
  MOZ_MUST_USE nsresult
145
  DecodeFinalHuffmanCharacter(const HuffmanIncomingTable *table, uint8_t &c,
146
                              uint8_t &bitsLeft);
147
148
  nsCString mHeaderStatus;
149
  nsCString mHeaderHost;
150
  nsCString mHeaderScheme;
151
  nsCString mHeaderPath;
152
  nsCString mHeaderMethod;
153
154
  // state variables when DecodeBlock() is on the stack
155
  uint32_t mOffset;
156
  const uint8_t *mData;
157
  uint32_t mDataLen;
158
  bool mSeenNonColonHeader;
159
  bool mIsPush;
160
};
161
162
163
class Http2Compressor final : public Http2BaseCompressor
164
{
165
public:
166
  Http2Compressor() : mParsedContentLength(-1),
167
                      mBufferSizeChangeWaiting(false),
168
                      mLowestBufferSizeWaiting(0)
169
0
  {
170
0
    mPeakSizeID = Telemetry::HPACK_PEAK_SIZE_COMPRESSOR;
171
0
    mPeakCountID = Telemetry::HPACK_PEAK_COUNT_COMPRESSOR;
172
0
  };
173
  virtual ~Http2Compressor() = default;
174
175
  // HTTP/1 formatted header block as input - HTTP/2 formatted
176
  // header block as output
177
  MOZ_MUST_USE nsresult EncodeHeaderBlock(const nsCString &nvInput,
178
                                          const nsACString &method,
179
                                          const nsACString &path,
180
                                          const nsACString &host,
181
                                          const nsACString &scheme,
182
                                          bool connectForm,
183
                                          nsACString &output);
184
185
0
  int64_t GetParsedContentLength() { return mParsedContentLength; } // -1 on not found
186
187
  void SetMaxBufferSize(uint32_t maxBufferSize);
188
189
private:
190
  enum outputCode {
191
    kNeverIndexedLiteral,
192
    kPlainLiteral,
193
    kIndexedLiteral,
194
    kIndex
195
  };
196
197
  void DoOutput(Http2Compressor::outputCode code,
198
                const class nvPair *pair, uint32_t index);
199
  void EncodeInteger(uint32_t prefixLen, uint32_t val);
200
  void ProcessHeader(const nvPair inputPair, bool noLocalIndex,
201
                     bool neverIndex);
202
  void HuffmanAppend(const nsCString &value);
203
  void EncodeTableSizeChange(uint32_t newMaxSize);
204
205
  int64_t mParsedContentLength;
206
  bool mBufferSizeChangeWaiting;
207
  uint32_t mLowestBufferSizeWaiting;
208
};
209
210
} // namespace net
211
} // namespace mozilla
212
213
#endif // mozilla_net_Http2Compression_Internal_h