1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/protocol/http/Http2Compression.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,198 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef mozilla_net_Http2Compression_Internal_h 1.10 +#define mozilla_net_Http2Compression_Internal_h 1.11 + 1.12 +// HPACK 1.13 +// tools.ietf.org/html/draft-ietf-httpbis-header-compression-04 1.14 + 1.15 +#include "mozilla/Attributes.h" 1.16 +#include "nsDeque.h" 1.17 +#include "nsString.h" 1.18 + 1.19 +namespace mozilla { 1.20 +namespace net { 1.21 + 1.22 +struct HuffmanIncomingTable; 1.23 + 1.24 +void Http2CompressionCleanup(); 1.25 + 1.26 +class nvPair 1.27 +{ 1.28 +public: 1.29 +nvPair(const nsACString &name, const nsACString &value) 1.30 + : mName(name) 1.31 + , mValue(value) 1.32 + { } 1.33 + 1.34 + uint32_t Size() const { return mName.Length() + mValue.Length() + 32; } 1.35 + 1.36 + nsCString mName; 1.37 + nsCString mValue; 1.38 +}; 1.39 + 1.40 +class nvFIFO 1.41 +{ 1.42 +public: 1.43 + nvFIFO(); 1.44 + ~nvFIFO(); 1.45 + void AddElement(const nsCString &name, const nsCString &value); 1.46 + void AddElement(const nsCString &name); 1.47 + void RemoveElement(); 1.48 + uint32_t ByteCount() const; 1.49 + uint32_t Length() const; 1.50 + uint32_t VariableLength() const; 1.51 + void Clear(); 1.52 + const nvPair *operator[] (int32_t index) const; 1.53 + 1.54 +private: 1.55 + uint32_t mByteCount; 1.56 + nsDeque mTable; 1.57 +}; 1.58 + 1.59 +class Http2BaseCompressor 1.60 +{ 1.61 +public: 1.62 + Http2BaseCompressor(); 1.63 + virtual ~Http2BaseCompressor() { }; 1.64 + 1.65 +protected: 1.66 + // this will become a HTTP/2 SETTINGS value in a future draft 1.67 + const static uint32_t kDefaultMaxBuffer = 4096; 1.68 + 1.69 + virtual void ClearHeaderTable(); 1.70 + virtual void UpdateReferenceSet(int32_t delta); 1.71 + virtual void IncrementReferenceSetIndices(); 1.72 + virtual void MakeRoom(uint32_t amount) = 0; 1.73 + 1.74 + nsAutoTArray<uint32_t, 64> mReferenceSet; // list of indicies 1.75 + 1.76 + // the alternate set is used to track the emitted headers when 1.77 + // processing input for a header set. The input to the compressor 1.78 + // is a series of nvpairs, the input to the decompressor is the 1.79 + // series of op codes that make up the header block. 1.80 + // 1.81 + // after processing the input the compressor compares the alternate 1.82 + // set to the inherited reference set and generates indicies to 1.83 + // toggle off any members of alternate - inherited. the alternate 1.84 + // then becomes the inherited set for the next header set. 1.85 + // 1.86 + // after processing the input the decompressor comapres the alternate 1.87 + // set to the inherited reference set and generates headers for 1.88 + // anything implicit in reference - alternate. 1.89 + nsAutoTArray<uint32_t, 64> mAlternateReferenceSet; // list of indicies 1.90 + 1.91 + nsACString *mOutput; 1.92 + nvFIFO mHeaderTable; 1.93 + 1.94 + uint32_t mMaxBuffer; 1.95 +}; 1.96 + 1.97 +class Http2Compressor; 1.98 + 1.99 +class Http2Decompressor MOZ_FINAL : public Http2BaseCompressor 1.100 +{ 1.101 +public: 1.102 + Http2Decompressor() { }; 1.103 + virtual ~Http2Decompressor() { } ; 1.104 + 1.105 + // NS_OK: Produces the working set of HTTP/1 formatted headers 1.106 + nsresult DecodeHeaderBlock(const uint8_t *data, uint32_t datalen, 1.107 + nsACString &output); 1.108 + 1.109 + void GetStatus(nsACString &hdr) { hdr = mHeaderStatus; } 1.110 + void GetHost(nsACString &hdr) { hdr = mHeaderHost; } 1.111 + void GetScheme(nsACString &hdr) { hdr = mHeaderScheme; } 1.112 + void GetPath(nsACString &hdr) { hdr = mHeaderPath; } 1.113 + void GetMethod(nsACString &hdr) { hdr = mHeaderMethod; } 1.114 + void SetCompressor(Http2Compressor *compressor) { mCompressor = compressor; } 1.115 + 1.116 +protected: 1.117 + virtual void MakeRoom(uint32_t amount) MOZ_OVERRIDE; 1.118 + 1.119 +private: 1.120 + nsresult DoIndexed(); 1.121 + nsresult DoLiteralWithoutIndex(); 1.122 + nsresult DoLiteralWithIncremental(); 1.123 + nsresult DoLiteralInternal(nsACString &, nsACString &); 1.124 + 1.125 + nsresult DecodeInteger(uint32_t prefixLen, uint32_t &result); 1.126 + nsresult OutputHeader(uint32_t index); 1.127 + nsresult OutputHeader(const nsACString &name, const nsACString &value); 1.128 + 1.129 + nsresult CopyHeaderString(uint32_t index, nsACString &name); 1.130 + nsresult CopyStringFromInput(uint32_t index, nsACString &val); 1.131 + uint8_t ExtractByte(uint8_t bitsLeft, uint32_t &bytesConsumed); 1.132 + nsresult CopyHuffmanStringFromInput(uint32_t index, nsACString &val); 1.133 + nsresult DecodeHuffmanCharacter(HuffmanIncomingTable *table, uint8_t &c, 1.134 + uint32_t &bytesConsumed, uint8_t &bitsLeft); 1.135 + nsresult DecodeFinalHuffmanCharacter(HuffmanIncomingTable *table, uint8_t &c, 1.136 + uint8_t &bitsLeft); 1.137 + 1.138 + Http2Compressor *mCompressor; 1.139 + 1.140 + nsCString mHeaderStatus; 1.141 + nsCString mHeaderHost; 1.142 + nsCString mHeaderScheme; 1.143 + nsCString mHeaderPath; 1.144 + nsCString mHeaderMethod; 1.145 + 1.146 + // state variables when DecodeBlock() is on the stack 1.147 + uint32_t mOffset; 1.148 + const uint8_t *mData; 1.149 + uint32_t mDataLen; 1.150 +}; 1.151 + 1.152 + 1.153 +class Http2Compressor MOZ_FINAL : public Http2BaseCompressor 1.154 +{ 1.155 +public: 1.156 + Http2Compressor() : mParsedContentLength(-1) { }; 1.157 + virtual ~Http2Compressor() { } 1.158 + 1.159 + // HTTP/1 formatted header block as input - HTTP/2 formatted 1.160 + // header block as output 1.161 + nsresult EncodeHeaderBlock(const nsCString &nvInput, 1.162 + const nsACString &method, const nsACString &path, 1.163 + const nsACString &host, const nsACString &scheme, 1.164 + nsACString &output); 1.165 + 1.166 + int64_t GetParsedContentLength() { return mParsedContentLength; } // -1 on not found 1.167 + 1.168 + void SetMaxBufferSize(uint32_t maxBufferSize); 1.169 + nsresult SetMaxBufferSizeInternal(uint32_t maxBufferSize); 1.170 + 1.171 +protected: 1.172 + virtual void ClearHeaderTable() MOZ_OVERRIDE; 1.173 + virtual void UpdateReferenceSet(int32_t delta) MOZ_OVERRIDE; 1.174 + virtual void IncrementReferenceSetIndices() MOZ_OVERRIDE; 1.175 + virtual void MakeRoom(uint32_t amount) MOZ_OVERRIDE; 1.176 + 1.177 +private: 1.178 + enum outputCode { 1.179 + kPlainLiteral, 1.180 + kIndexedLiteral, 1.181 + kToggleOff, 1.182 + kToggleOn, 1.183 + kNop 1.184 + }; 1.185 + 1.186 + void DoOutput(Http2Compressor::outputCode code, 1.187 + const class nvPair *pair, uint32_t index); 1.188 + void EncodeInteger(uint32_t prefixLen, uint32_t val); 1.189 + void ProcessHeader(const nvPair inputPair); 1.190 + void HuffmanAppend(const nsCString &value); 1.191 + 1.192 + int64_t mParsedContentLength; 1.193 + uint32_t mMaxBufferSetting; 1.194 + 1.195 + nsAutoTArray<uint32_t, 64> mImpliedReferenceSet; 1.196 +}; 1.197 + 1.198 +} // namespace mozilla::net 1.199 +} // namespace mozilla 1.200 + 1.201 +#endif // mozilla_net_Http2Compression_Internal_h