summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.h
blob: 3650bef572e6ebf34d0b405728de54c3c9be5db0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
// Copyright (c) 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef QUICHE_QUIC_CORE_HTTP_HTTP_DECODER_H_
#define QUICHE_QUIC_CORE_HTTP_HTTP_DECODER_H_

#include <cstdint>

#include "net/third_party/quiche/src/quic/core/http/http_frames.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"

namespace quic {

namespace test {

class HttpDecoderPeer;

}  // namespace test

class QuicDataReader;

// A class for decoding the HTTP frames that are exchanged in an HTTP over QUIC
// session.
class QUIC_EXPORT_PRIVATE HttpDecoder {
 public:
  class QUIC_EXPORT_PRIVATE Visitor {
   public:
    virtual ~Visitor() {}

    // Called if an error is detected.
    virtual void OnError(HttpDecoder* decoder) = 0;

    // All the following methods return true to continue decoding,
    // and false to pause it.
    // On*FrameStart() methods are called after the frame header is completely
    // processed.  At that point it is safe to consume |header_length| bytes.

    // Called when a CANCEL_PUSH frame has been successfully parsed.
    virtual bool OnCancelPushFrame(const CancelPushFrame& frame) = 0;

    // Called when a MAX_PUSH_ID frame has been successfully parsed.
    virtual bool OnMaxPushIdFrame(const MaxPushIdFrame& frame) = 0;

    // Called when a GOAWAY frame has been successfully parsed.
    virtual bool OnGoAwayFrame(const GoAwayFrame& frame) = 0;

    // Called when a SETTINGS frame has been received.
    virtual bool OnSettingsFrameStart(QuicByteCount header_length) = 0;

    // Called when a SETTINGS frame has been successfully parsed.
    virtual bool OnSettingsFrame(const SettingsFrame& frame) = 0;

    // Called when a DATA frame has been received.
    // |header_length| and |payload_length| are the length of DATA frame header
    // and payload, respectively.
    virtual bool OnDataFrameStart(QuicByteCount header_length,
                                  QuicByteCount payload_length) = 0;
    // Called when part of the payload of a DATA frame has been read.  May be
    // called multiple times for a single frame.  |payload| is guaranteed to be
    // non-empty.
    virtual bool OnDataFramePayload(quiche::QuicheStringPiece payload) = 0;
    // Called when a DATA frame has been completely processed.
    virtual bool OnDataFrameEnd() = 0;

    // Called when a HEADERS frame has been received.
    // |header_length| and |payload_length| are the length of HEADERS frame
    // header and payload, respectively.
    virtual bool OnHeadersFrameStart(QuicByteCount header_length,
                                     QuicByteCount payload_length) = 0;
    // Called when part of the payload of a HEADERS frame has been read.  May be
    // called multiple times for a single frame.  |payload| is guaranteed to be
    // non-empty.
    virtual bool OnHeadersFramePayload(quiche::QuicheStringPiece payload) = 0;
    // Called when a HEADERS frame has been completely processed.
    virtual bool OnHeadersFrameEnd() = 0;

    // Called when a PUSH_PROMISE frame has been received.
    virtual bool OnPushPromiseFrameStart(QuicByteCount header_length) = 0;
    // Called when the Push ID field of a PUSH_PROMISE frame has been parsed.
    // Called exactly once for a valid PUSH_PROMISE frame.
    // |push_id_length| is the length of the push ID field.
    // |header_block_length| is the length of the compressed header block.
    virtual bool OnPushPromiseFramePushId(
        PushId push_id,
        QuicByteCount push_id_length,
        QuicByteCount header_block_length) = 0;
    // Called when part of the header block of a PUSH_PROMISE frame has been
    // read. May be called multiple times for a single frame.  |payload| is
    // guaranteed to be non-empty.
    virtual bool OnPushPromiseFramePayload(
        quiche::QuicheStringPiece payload) = 0;
    // Called when a PUSH_PROMISE frame has been completely processed.
    virtual bool OnPushPromiseFrameEnd() = 0;

    // Called when a PRIORITY_UPDATE frame has been received.
    // |header_length| contains PRIORITY_UPDATE frame length and payload length.
    virtual bool OnPriorityUpdateFrameStart(QuicByteCount header_length) = 0;

    // Called when a PRIORITY_UPDATE frame has been successfully parsed.
    virtual bool OnPriorityUpdateFrame(const PriorityUpdateFrame& frame) = 0;

    // Called when a frame of unknown type |frame_type| has been received.
    // Frame type might be reserved, Visitor must make sure to ignore.
    // |header_length| and |payload_length| are the length of the frame header
    // and payload, respectively.
    virtual bool OnUnknownFrameStart(uint64_t frame_type,
                                     QuicByteCount header_length,
                                     QuicByteCount payload_length) = 0;
    // Called when part of the payload of the unknown frame has been read.  May
    // be called multiple times for a single frame.  |payload| is guaranteed to
    // be non-empty.
    virtual bool OnUnknownFramePayload(quiche::QuicheStringPiece payload) = 0;
    // Called when the unknown frame has been completely processed.
    virtual bool OnUnknownFrameEnd() = 0;
  };

  // |visitor| must be non-null, and must outlive HttpDecoder.
  explicit HttpDecoder(Visitor* visitor);

  ~HttpDecoder();

  // Processes the input and invokes the appropriate visitor methods, until a
  // visitor method returns false or an error occurs.  Returns the number of
  // bytes processed.  Does not process any input if called after an error.
  // Paused processing can be resumed by calling ProcessInput() again with the
  // unprocessed portion of data.  Must not be called after an error has
  // occurred.
  QuicByteCount ProcessInput(const char* data, QuicByteCount len);

  // Returns an error code other than QUIC_NO_ERROR if and only if
  // Visitor::OnError() has been called.
  QuicErrorCode error() const { return error_; }

  const std::string& error_detail() const { return error_detail_; }

 private:
  friend test::HttpDecoderPeer;

  // Represents the current state of the parsing state machine.
  enum HttpDecoderState {
    STATE_READING_FRAME_LENGTH,
    STATE_READING_FRAME_TYPE,
    STATE_READING_FRAME_PAYLOAD,
    STATE_FINISH_PARSING,
    STATE_ERROR
  };

  // Reads the type of a frame from |reader|. Sets error_ and error_detail_
  // if there are any errors.  Also calls OnDataFrameStart() or
  // OnHeadersFrameStart() for appropriate frame types.
  void ReadFrameType(QuicDataReader* reader);

  // Reads the length of a frame from |reader|. Sets error_ and error_detail_
  // if there are any errors.  Returns whether processing should continue.
  bool ReadFrameLength(QuicDataReader* reader);

  // Reads the payload of the current frame from |reader| and processes it,
  // possibly buffering the data or invoking the visitor.  Returns whether
  // processing should continue.
  bool ReadFramePayload(QuicDataReader* reader);

  // Optionally parses buffered data; calls visitor method to signal that frame
  // had been parsed completely.  Returns whether processing should continue.
  bool FinishParsing();

  // Discards any remaining frame payload from |reader|.
  void DiscardFramePayload(QuicDataReader* reader);

  // Buffers any remaining frame payload from |reader| into |buffer_|.
  void BufferFramePayload(QuicDataReader* reader);

  // Buffers any remaining frame length field from |reader| into
  // |length_buffer_|.
  void BufferFrameLength(QuicDataReader* reader);

  // Buffers any remaining frame type field from |reader| into |type_buffer_|.
  void BufferFrameType(QuicDataReader* reader);

  // Buffers at most |remaining_push_id_length_| from |reader| to
  // |push_id_buffer_|.
  void BufferPushId(QuicDataReader* reader);

  // Sets |error_| and |error_detail_| accordingly.
  void RaiseError(QuicErrorCode error, std::string error_detail);

  // Parses the payload of a SETTINGS frame from |reader| into |frame|.
  bool ParseSettingsFrame(QuicDataReader* reader, SettingsFrame* frame);

  // Parses the payload of a PRIORITY_UPDATE frame from |reader| into |frame|.
  bool ParsePriorityUpdateFrame(QuicDataReader* reader,
                                PriorityUpdateFrame* frame);

  // Returns the max frame size of a given |frame_type|.
  QuicByteCount MaxFrameLength(uint64_t frame_type);

  // Visitor to invoke when messages are parsed.
  Visitor* const visitor_;  // Unowned.
  // Current state of the parsing.
  HttpDecoderState state_;
  // Type of the frame currently being parsed.
  uint64_t current_frame_type_;
  // Size of the frame's length field.
  QuicByteCount current_length_field_length_;
  // Remaining length that's needed for the frame's length field.
  QuicByteCount remaining_length_field_length_;
  // Length of the payload of the frame currently being parsed.
  QuicByteCount current_frame_length_;
  // Remaining payload bytes to be parsed.
  QuicByteCount remaining_frame_length_;
  // Length of the frame's type field.
  QuicByteCount current_type_field_length_;
  // Remaining length that's needed for the frame's type field.
  QuicByteCount remaining_type_field_length_;
  // Length of PUSH_PROMISE frame's push id.
  QuicByteCount current_push_id_length_;
  // Remaining length that's needed for PUSH_PROMISE frame's push id field.
  QuicByteCount remaining_push_id_length_;
  // Last error.
  QuicErrorCode error_;
  // The issue which caused |error_|
  std::string error_detail_;
  // Remaining unparsed data.
  std::string buffer_;
  // Remaining unparsed length field data.
  std::array<char, sizeof(uint64_t)> length_buffer_;
  // Remaining unparsed type field data.
  std::array<char, sizeof(uint64_t)> type_buffer_;
  // Remaining unparsed push id data.
  std::array<char, sizeof(uint64_t)> push_id_buffer_;
};

}  // namespace quic

#endif  // QUICHE_QUIC_CORE_HTTP_HTTP_DECODER_H_