1 // Copyright 2016 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef QUICHE_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_H_ 6 #define QUICHE_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_H_ 7 8 // HpackEntryDecoder decodes a single HPACK entry (i.e. one header or one 9 // dynamic table size update), in a resumable fashion. The first call, Start(), 10 // must provide a non-empty decode buffer. Continue with calls to Resume() if 11 // Start, and any subsequent calls to Resume, returns kDecodeInProgress. 12 13 #include <string> 14 15 #include "quiche/http2/decoder/decode_buffer.h" 16 #include "quiche/http2/decoder/decode_status.h" 17 #include "quiche/http2/hpack/decoder/hpack_decoding_error.h" 18 #include "quiche/http2/hpack/decoder/hpack_entry_decoder_listener.h" 19 #include "quiche/http2/hpack/decoder/hpack_entry_type_decoder.h" 20 #include "quiche/http2/hpack/decoder/hpack_string_decoder.h" 21 #include "quiche/http2/hpack/http2_hpack_constants.h" 22 #include "quiche/common/platform/api/quiche_export.h" 23 #include "quiche/common/platform/api/quiche_logging.h" 24 25 namespace http2 { 26 27 class QUICHE_EXPORT HpackEntryDecoder { 28 public: 29 enum class EntryDecoderState { 30 // Have started decoding the type/varint, but didn't finish on the previous 31 // attempt. Next state is kResumeDecodingType or kDecodedType. 32 kResumeDecodingType, 33 34 // Have just finished decoding the type/varint. Final state if the type is 35 // kIndexedHeader or kDynamicTableSizeUpdate. Otherwise, the next state is 36 // kStartDecodingName (if the varint is 0), else kStartDecodingValue. 37 kDecodedType, 38 39 // Ready to start decoding the literal name of a header entry. Next state 40 // is kResumeDecodingName (if the name is split across decode buffers), 41 // else kStartDecodingValue. 42 kStartDecodingName, 43 44 // Resume decoding the literal name of a header that is split across decode 45 // buffers. 46 kResumeDecodingName, 47 48 // Ready to start decoding the literal value of a header entry. Final state 49 // if the value string is entirely in the decode buffer, else the next state 50 // is kResumeDecodingValue. 51 kStartDecodingValue, 52 53 // Resume decoding the literal value of a header that is split across decode 54 // buffers. 55 kResumeDecodingValue, 56 }; 57 58 // Only call when the decode buffer has data (i.e. HpackBlockDecoder must 59 // not call until there is data). 60 DecodeStatus Start(DecodeBuffer* db, HpackEntryDecoderListener* listener); 61 62 // Only call Resume if the previous call (Start or Resume) returned 63 // kDecodeInProgress; Resume is also called from Start when it has succeeded 64 // in decoding the entry type and its varint. 65 DecodeStatus Resume(DecodeBuffer* db, HpackEntryDecoderListener* listener); 66 67 // Return error code after decoding error occurred. error()68 HpackDecodingError error() const { return error_; } 69 70 std::string DebugString() const; 71 void OutputDebugString(std::ostream& out) const; 72 73 private: 74 // Implements handling state kDecodedType. 75 bool DispatchOnType(HpackEntryDecoderListener* listener); 76 77 HpackEntryTypeDecoder entry_type_decoder_; 78 HpackStringDecoder string_decoder_; 79 EntryDecoderState state_ = EntryDecoderState(); 80 HpackDecodingError error_ = HpackDecodingError::kOk; 81 }; 82 83 QUICHE_EXPORT std::ostream& operator<<(std::ostream& out, 84 const HpackEntryDecoder& v); 85 QUICHE_EXPORT std::ostream& operator<<( 86 std::ostream& out, HpackEntryDecoder::EntryDecoderState state); 87 88 } // namespace http2 89 90 #endif // QUICHE_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_H_ 91