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