Line data Source code
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 0 : class nvPair
26 : {
27 : public:
28 0 : nvPair(const nsACString &name, const nsACString &value)
29 0 : : mName(name)
30 0 : , 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 0 : Http2Decompressor()
103 0 : {
104 0 : mPeakSizeID = Telemetry::HPACK_PEAK_SIZE_DECOMPRESSOR;
105 0 : mPeakCountID = Telemetry::HPACK_PEAK_COUNT_DECOMPRESSOR;
106 0 : };
107 0 : virtual ~Http2Decompressor() { } ;
108 :
109 : // NS_OK: Produces the working set of HTTP/1 formatted headers
110 : MOZ_MUST_USE nsresult DecodeHeaderBlock(const uint8_t *data,
111 : uint32_t datalen, nsACString &output,
112 : bool isPush);
113 :
114 0 : void GetStatus(nsACString &hdr) { hdr = mHeaderStatus; }
115 0 : void GetHost(nsACString &hdr) { hdr = mHeaderHost; }
116 0 : void GetScheme(nsACString &hdr) { hdr = mHeaderScheme; }
117 0 : void GetPath(nsACString &hdr) { hdr = mHeaderPath; }
118 0 : void GetMethod(nsACString &hdr) { hdr = mHeaderMethod; }
119 :
120 : private:
121 : MOZ_MUST_USE nsresult DoIndexed();
122 : MOZ_MUST_USE nsresult DoLiteralWithoutIndex();
123 : MOZ_MUST_USE nsresult DoLiteralWithIncremental();
124 : MOZ_MUST_USE nsresult DoLiteralInternal(nsACString &, nsACString &, uint32_t);
125 : MOZ_MUST_USE nsresult DoLiteralNeverIndexed();
126 : MOZ_MUST_USE nsresult DoContextUpdate();
127 :
128 : MOZ_MUST_USE nsresult DecodeInteger(uint32_t prefixLen, uint32_t &result);
129 : MOZ_MUST_USE nsresult OutputHeader(uint32_t index);
130 : MOZ_MUST_USE nsresult OutputHeader(const nsACString &name, const nsACString &value);
131 :
132 : MOZ_MUST_USE nsresult CopyHeaderString(uint32_t index, nsACString &name);
133 : MOZ_MUST_USE nsresult CopyStringFromInput(uint32_t index, nsACString &val);
134 : uint8_t ExtractByte(uint8_t bitsLeft, uint32_t &bytesConsumed);
135 : MOZ_MUST_USE nsresult CopyHuffmanStringFromInput(uint32_t index, nsACString &val);
136 : MOZ_MUST_USE nsresult
137 : DecodeHuffmanCharacter(const HuffmanIncomingTable *table, uint8_t &c,
138 : uint32_t &bytesConsumed, uint8_t &bitsLeft);
139 : MOZ_MUST_USE nsresult
140 : DecodeFinalHuffmanCharacter(const HuffmanIncomingTable *table, uint8_t &c,
141 : uint8_t &bitsLeft);
142 :
143 : nsCString mHeaderStatus;
144 : nsCString mHeaderHost;
145 : nsCString mHeaderScheme;
146 : nsCString mHeaderPath;
147 : nsCString mHeaderMethod;
148 :
149 : // state variables when DecodeBlock() is on the stack
150 : uint32_t mOffset;
151 : const uint8_t *mData;
152 : uint32_t mDataLen;
153 : bool mSeenNonColonHeader;
154 : bool mIsPush;
155 : };
156 :
157 :
158 : class Http2Compressor final : public Http2BaseCompressor
159 : {
160 : public:
161 0 : Http2Compressor() : mParsedContentLength(-1),
162 : mBufferSizeChangeWaiting(false),
163 0 : mLowestBufferSizeWaiting(0)
164 : {
165 0 : mPeakSizeID = Telemetry::HPACK_PEAK_SIZE_COMPRESSOR;
166 0 : mPeakCountID = Telemetry::HPACK_PEAK_COUNT_COMPRESSOR;
167 0 : };
168 0 : virtual ~Http2Compressor() { }
169 :
170 : // HTTP/1 formatted header block as input - HTTP/2 formatted
171 : // header block as output
172 : MOZ_MUST_USE nsresult EncodeHeaderBlock(const nsCString &nvInput,
173 : const nsACString &method,
174 : const nsACString &path,
175 : const nsACString &host,
176 : const nsACString &scheme,
177 : bool connectForm,
178 : nsACString &output);
179 :
180 0 : int64_t GetParsedContentLength() { return mParsedContentLength; } // -1 on not found
181 :
182 : void SetMaxBufferSize(uint32_t maxBufferSize);
183 :
184 : private:
185 : enum outputCode {
186 : kNeverIndexedLiteral,
187 : kPlainLiteral,
188 : kIndexedLiteral,
189 : kIndex
190 : };
191 :
192 : void DoOutput(Http2Compressor::outputCode code,
193 : const class nvPair *pair, uint32_t index);
194 : void EncodeInteger(uint32_t prefixLen, uint32_t val);
195 : void ProcessHeader(const nvPair inputPair, bool noLocalIndex,
196 : bool neverIndex);
197 : void HuffmanAppend(const nsCString &value);
198 : void EncodeTableSizeChange(uint32_t newMaxSize);
199 :
200 : int64_t mParsedContentLength;
201 : bool mBufferSizeChangeWaiting;
202 : uint32_t mLowestBufferSizeWaiting;
203 : };
204 :
205 : } // namespace net
206 : } // namespace mozilla
207 :
208 : #endif // mozilla_net_Http2Compression_Internal_h
|