1 // Copyright (c) 2018 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 #include "quiche/quic/core/qpack/qpack_encoder_stream_receiver.h"
6
7 #include "absl/strings/string_view.h"
8 #include "quiche/http2/decoder/decode_buffer.h"
9 #include "quiche/http2/decoder/decode_status.h"
10 #include "quiche/quic/core/qpack/qpack_instructions.h"
11 #include "quiche/quic/platform/api/quic_logging.h"
12
13 namespace quic {
14
QpackEncoderStreamReceiver(Delegate * delegate)15 QpackEncoderStreamReceiver::QpackEncoderStreamReceiver(Delegate* delegate)
16 : instruction_decoder_(QpackEncoderStreamLanguage(), this),
17 delegate_(delegate),
18 error_detected_(false) {
19 QUICHE_DCHECK(delegate_);
20 }
21
Decode(absl::string_view data)22 void QpackEncoderStreamReceiver::Decode(absl::string_view data) {
23 if (data.empty() || error_detected_) {
24 return;
25 }
26
27 instruction_decoder_.Decode(data);
28 }
29
OnInstructionDecoded(const QpackInstruction * instruction)30 bool QpackEncoderStreamReceiver::OnInstructionDecoded(
31 const QpackInstruction* instruction) {
32 if (instruction == InsertWithNameReferenceInstruction()) {
33 delegate_->OnInsertWithNameReference(instruction_decoder_.s_bit(),
34 instruction_decoder_.varint(),
35 instruction_decoder_.value());
36 return true;
37 }
38
39 if (instruction == InsertWithoutNameReferenceInstruction()) {
40 delegate_->OnInsertWithoutNameReference(instruction_decoder_.name(),
41 instruction_decoder_.value());
42 return true;
43 }
44
45 if (instruction == DuplicateInstruction()) {
46 delegate_->OnDuplicate(instruction_decoder_.varint());
47 return true;
48 }
49
50 QUICHE_DCHECK_EQ(instruction, SetDynamicTableCapacityInstruction());
51 delegate_->OnSetDynamicTableCapacity(instruction_decoder_.varint());
52 return true;
53 }
54
OnInstructionDecodingError(QpackInstructionDecoder::ErrorCode error_code,absl::string_view error_message)55 void QpackEncoderStreamReceiver::OnInstructionDecodingError(
56 QpackInstructionDecoder::ErrorCode error_code,
57 absl::string_view error_message) {
58 QUICHE_DCHECK(!error_detected_);
59
60 error_detected_ = true;
61
62 QuicErrorCode quic_error_code;
63 switch (error_code) {
64 case QpackInstructionDecoder::ErrorCode::INTEGER_TOO_LARGE:
65 quic_error_code = QUIC_QPACK_ENCODER_STREAM_INTEGER_TOO_LARGE;
66 break;
67 case QpackInstructionDecoder::ErrorCode::STRING_LITERAL_TOO_LONG:
68 quic_error_code = QUIC_QPACK_ENCODER_STREAM_STRING_LITERAL_TOO_LONG;
69 break;
70 case QpackInstructionDecoder::ErrorCode::HUFFMAN_ENCODING_ERROR:
71 quic_error_code = QUIC_QPACK_ENCODER_STREAM_HUFFMAN_ENCODING_ERROR;
72 break;
73 default:
74 quic_error_code = QUIC_INTERNAL_ERROR;
75 }
76
77 delegate_->OnErrorDetected(quic_error_code, error_message);
78 }
79
80 } // namespace quic
81