Coverage Report

Created: 2026-03-28 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/trafficserver/include/proxy/http3/Http3Frame.h
Line
Count
Source
1
/** @file
2
 *
3
 *  A brief file description
4
 *
5
 *  @section license License
6
 *
7
 *  Licensed to the Apache Software Foundation (ASF) under one
8
 *  or more contributor license agreements.  See the NOTICE file
9
 *  distributed with this work for additional information
10
 *  regarding copyright ownership.  The ASF licenses this file
11
 *  to you under the Apache License, Version 2.0 (the
12
 *  "License"); you may not use this file except in compliance
13
 *  with the License.  You may obtain a copy of the License at
14
 *
15
 *      http://www.apache.org/licenses/LICENSE-2.0
16
 *
17
 *  Unless required by applicable law or agreed to in writing, software
18
 *  distributed under the License is distributed on an "AS IS" BASIS,
19
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
 *  See the License for the specific language governing permissions and
21
 *  limitations under the License.
22
 */
23
24
#pragma once
25
26
#include "tscore/Allocator.h"
27
#include "tscore/ink_memory.h"
28
#include "tscore/ink_assert.h"
29
#include "iocore/net/quic/QUICApplication.h"
30
#include "proxy/http3/Http3Types.h"
31
32
class Http3Frame
33
{
34
public:
35
  constexpr static size_t MAX_FRAM_HEADER_OVERHEAD = 128; ///< Type (i) + Length (i)
36
37
144
  Http3Frame() {}
38
  Http3Frame(IOBufferReader &reader);
39
  Http3Frame(Http3FrameType type);
40
  virtual ~Http3Frame();
41
42
  bool                       is_valid() const;
43
  uint64_t                   total_length() const;
44
  uint64_t                   length() const;
45
  Http3FrameType             type() const;
46
  bool                       update();
47
  virtual Ptr<IOBufferBlock> to_io_buffer_block() const;
48
  virtual void               reset(IOBufferReader &reader);
49
  static int                 length(const uint8_t *buf, size_t buf_len, uint64_t &length);
50
  static Http3FrameType      type(const uint8_t *buf, size_t buf_len);
51
52
protected:
53
  IOBufferReader *_reader           = nullptr;
54
  bool            _finished_reading = false;
55
  uint64_t        _length           = 0;
56
  Http3FrameType  _type             = Http3FrameType::UNKNOWN;
57
  size_t          _payload_offset   = 0;
58
  bool            _is_valid         = true;
59
60
  virtual bool _parse();
61
62
private:
63
  bool _is_ready = false;
64
};
65
66
class Http3UnknownFrame : public Http3Frame
67
{
68
public:
69
0
  Http3UnknownFrame() : Http3Frame() {}
70
  Http3UnknownFrame(IOBufferReader &reader);
71
72
  Ptr<IOBufferBlock> to_io_buffer_block() const override;
73
74
protected:
75
  const uint8_t *_buf     = nullptr;
76
  size_t         _buf_len = 0;
77
};
78
79
//
80
// DATA Frame
81
//
82
83
class Http3DataFrame : public Http3Frame
84
{
85
public:
86
10
  Http3DataFrame() : Http3Frame() {}
87
  Http3DataFrame(IOBufferReader &reader);
88
  Http3DataFrame(IOBufferReader &reader, size_t payload_len);
89
90
  Ptr<IOBufferBlock> to_io_buffer_block() const override;
91
  void               reset(IOBufferReader &reader) override;
92
93
  uint64_t payload_length() const;
94
95
  IOBufferReader *data() const;
96
97
private:
98
  // Head of IOBufferBlock chain to send
99
  Ptr<IOBufferBlock> _whole_frame;
100
  uint64_t           _payload_len = 0;
101
};
102
103
//
104
// HEADERS Frame
105
//
106
107
class Http3HeadersFrame : public Http3Frame
108
{
109
public:
110
5
  Http3HeadersFrame() : Http3Frame() {}
111
  Http3HeadersFrame(IOBufferReader &reader);
112
  Http3HeadersFrame(ats_unique_buf header_block, size_t header_block_len);
113
  ~Http3HeadersFrame();
114
115
  Ptr<IOBufferBlock> to_io_buffer_block() const override;
116
  void               reset(IOBufferReader &reader) override;
117
118
  const uint8_t *header_block() const;
119
  uint64_t       header_block_length() const;
120
121
protected:
122
  bool _parse() override;
123
124
private:
125
  uint8_t       *_header_block      = nullptr;
126
  ats_unique_buf _header_block_uptr = {nullptr};
127
  size_t         _header_block_len  = 0;
128
};
129
130
//
131
// SETTINGS Frame
132
//
133
134
class Http3SettingsFrame : public Http3Frame
135
{
136
public:
137
5
  Http3SettingsFrame() : Http3Frame(Http3FrameType::SETTINGS) {}
138
  Http3SettingsFrame(IOBufferReader &reader, uint32_t max_settings = 0);
139
140
  static constexpr size_t                         MAX_PAYLOAD_SIZE = 60;
141
  static constexpr std::array<Http3SettingsId, 4> VALID_SETTINGS_IDS{
142
    Http3SettingsId::HEADER_TABLE_SIZE,
143
    Http3SettingsId::MAX_FIELD_SECTION_SIZE,
144
    Http3SettingsId::QPACK_BLOCKED_STREAMS,
145
    Http3SettingsId::NUM_PLACEHOLDERS,
146
  };
147
148
  Ptr<IOBufferBlock> to_io_buffer_block() const override;
149
  void               reset(IOBufferReader &reader) override;
150
151
  Http3ErrorUPtr get_error() const;
152
153
  bool     contains(Http3SettingsId id) const;
154
  uint64_t get(Http3SettingsId id) const;
155
  void     set(Http3SettingsId id, uint64_t value);
156
157
protected:
158
  bool _parse() override;
159
160
private:
161
  uint32_t                            _max_settings = 0;
162
  std::map<Http3SettingsId, uint64_t> _settings;
163
  Http3ErrorCode                      _error_code;
164
  const char                         *_error_reason = nullptr;
165
};
166
167
using Http3FrameDeleterFunc  = void (*)(Http3Frame *p);
168
using Http3FrameUPtr         = std::unique_ptr<Http3Frame, Http3FrameDeleterFunc>;
169
using Http3DataFrameUPtr     = std::unique_ptr<Http3DataFrame, Http3FrameDeleterFunc>;
170
using Http3HeadersFrameUPtr  = std::unique_ptr<Http3HeadersFrame, Http3FrameDeleterFunc>;
171
using Http3SettingsFrameUPtr = std::unique_ptr<Http3SettingsFrame, Http3FrameDeleterFunc>;
172
173
using Http3FrameDeleterFunc = void (*)(Http3Frame *p);
174
using Http3FrameUPtr        = std::unique_ptr<Http3Frame, Http3FrameDeleterFunc>;
175
using Http3DataFrameUPtr    = std::unique_ptr<Http3DataFrame, Http3FrameDeleterFunc>;
176
using Http3HeadersFrameUPtr = std::unique_ptr<Http3HeadersFrame, Http3FrameDeleterFunc>;
177
178
extern ClassAllocator<Http3Frame, false>         http3FrameAllocator;
179
extern ClassAllocator<Http3DataFrame, false>     http3DataFrameAllocator;
180
extern ClassAllocator<Http3HeadersFrame, false>  http3HeadersFrameAllocator;
181
extern ClassAllocator<Http3SettingsFrame, false> http3SettingsFrameAllocator;
182
183
class Http3FrameDeleter
184
{
185
public:
186
  static void
187
  delete_null_frame(Http3Frame *frame)
188
0
  {
189
0
    ink_assert(frame == nullptr);
190
0
  }
191
192
  static void
193
  delete_frame(Http3Frame *frame)
194
129
  {
195
129
    frame->~Http3Frame();
196
129
    http3FrameAllocator.free(static_cast<Http3Frame *>(frame));
197
129
  }
198
199
  static void
200
  delete_data_frame(Http3Frame *frame)
201
10
  {
202
10
    frame->~Http3Frame();
203
10
    http3DataFrameAllocator.free(static_cast<Http3DataFrame *>(frame));
204
10
  }
205
206
  static void
207
  delete_headers_frame(Http3Frame *frame)
208
5
  {
209
5
    frame->~Http3Frame();
210
5
    http3HeadersFrameAllocator.free(static_cast<Http3HeadersFrame *>(frame));
211
5
  }
212
213
  static void
214
  delete_settings_frame(Http3Frame *frame)
215
5
  {
216
5
    frame->~Http3Frame();
217
5
    http3SettingsFrameAllocator.free(static_cast<Http3SettingsFrame *>(frame));
218
5
  }
219
};
220
221
//
222
// Http3FrameFactory
223
//
224
class Http3FrameFactory
225
{
226
public:
227
  /*
228
   * This is for an empty Http3FrameUPtr.
229
   * Empty frames are used for variable initialization and return value of frame creation failure
230
   */
231
  static Http3FrameUPtr create_null_frame();
232
233
  /*
234
   * This is used for creating a Http3Frame object based on received data.
235
   */
236
  static Http3FrameUPtr create(IOBufferReader &reader);
237
238
  /*
239
   * This works almost the same as create() but it reuses created objects for performance.
240
   * If you create a frame object which has the same frame type that you created before, the object will be reset by new data.
241
   */
242
  std::shared_ptr<Http3Frame> fast_create(IOBufferReader &reader);
243
244
  /*
245
   * Creates a HEADERS frame.
246
   */
247
  static Http3HeadersFrameUPtr create_headers_frame(const uint8_t *header_block, size_t header_block_len);
248
  static Http3HeadersFrameUPtr create_headers_frame(IOBufferReader *header_block_reader, size_t header_block_len);
249
250
  /*
251
   * Creates a DATA frame.
252
   */
253
  static Http3DataFrameUPtr create_data_frame(IOBufferReader *reader, size_t data_len);
254
255
private:
256
  std::shared_ptr<Http3Frame> _unknown_frame        = nullptr;
257
  std::shared_ptr<Http3Frame> _reusable_frames[256] = {nullptr};
258
};