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 "QUICApplication.h" 30 #include "Http3Types.h" 31 32 class Http3Frame 33 { 34 public: 35 constexpr static size_t MAX_FRAM_HEADER_OVERHEAD = 128; ///< Type (i) + Length (i) 36 Http3Frame()37 Http3Frame() {} 38 Http3Frame(const uint8_t *buf, size_t len); 39 Http3Frame(Http3FrameType type); ~Http3Frame()40 virtual ~Http3Frame() {} 41 42 uint64_t total_length() const; 43 uint64_t length() const; 44 Http3FrameType type() const; 45 virtual void store(uint8_t *buf, size_t *len) const; 46 virtual void reset(const uint8_t *buf, size_t len); 47 static int length(const uint8_t *buf, size_t buf_len, uint64_t &length); 48 static Http3FrameType type(const uint8_t *buf, size_t buf_len); 49 50 protected: 51 uint64_t _length = 0; 52 Http3FrameType _type = Http3FrameType::UNKNOWN; 53 size_t _payload_offset = 0; 54 }; 55 56 class Http3UnknownFrame : public Http3Frame 57 { 58 public: Http3UnknownFrame()59 Http3UnknownFrame() : Http3Frame() {} 60 Http3UnknownFrame(const uint8_t *buf, size_t len); 61 62 void store(uint8_t *buf, size_t *len) const override; 63 64 protected: 65 const uint8_t *_buf = nullptr; 66 size_t _buf_len = 0; 67 }; 68 69 // 70 // DATA Frame 71 // 72 73 class Http3DataFrame : public Http3Frame 74 { 75 public: Http3DataFrame()76 Http3DataFrame() : Http3Frame() {} 77 Http3DataFrame(const uint8_t *buf, size_t len); 78 Http3DataFrame(ats_unique_buf payload, size_t payload_len); 79 80 void store(uint8_t *buf, size_t *len) const override; 81 void reset(const uint8_t *buf, size_t len) override; 82 83 const uint8_t *payload() const; 84 uint64_t payload_length() const; 85 86 private: 87 const uint8_t *_payload = nullptr; 88 ats_unique_buf _payload_uptr = {nullptr}; 89 size_t _payload_len = 0; 90 }; 91 92 // 93 // HEADERS Frame 94 // 95 96 class Http3HeadersFrame : public Http3Frame 97 { 98 public: Http3HeadersFrame()99 Http3HeadersFrame() : Http3Frame() {} 100 Http3HeadersFrame(const uint8_t *buf, size_t len); 101 Http3HeadersFrame(ats_unique_buf header_block, size_t header_block_len); 102 103 void store(uint8_t *buf, size_t *len) const override; 104 void reset(const uint8_t *buf, size_t len) override; 105 106 const uint8_t *header_block() const; 107 uint64_t header_block_length() const; 108 109 private: 110 const uint8_t *_header_block = nullptr; 111 ats_unique_buf _header_block_uptr = {nullptr}; 112 size_t _header_block_len = 0; 113 }; 114 115 // 116 // SETTINGS Frame 117 // 118 119 class Http3SettingsFrame : public Http3Frame 120 { 121 public: Http3SettingsFrame()122 Http3SettingsFrame() : Http3Frame(Http3FrameType::SETTINGS) {} 123 Http3SettingsFrame(const uint8_t *buf, size_t len, uint32_t max_settings = 0); 124 125 static constexpr size_t MAX_PAYLOAD_SIZE = 60; 126 static constexpr std::array<Http3SettingsId, 4> VALID_SETTINGS_IDS{ 127 Http3SettingsId::HEADER_TABLE_SIZE, 128 Http3SettingsId::MAX_HEADER_LIST_SIZE, 129 Http3SettingsId::QPACK_BLOCKED_STREAMS, 130 Http3SettingsId::NUM_PLACEHOLDERS, 131 }; 132 133 void store(uint8_t *buf, size_t *len) const override; 134 void reset(const uint8_t *buf, size_t len) override; 135 136 bool is_valid() const; 137 Http3ErrorUPtr get_error() const; 138 139 bool contains(Http3SettingsId id) const; 140 uint64_t get(Http3SettingsId id) const; 141 void set(Http3SettingsId id, uint64_t value); 142 143 private: 144 std::map<Http3SettingsId, uint64_t> _settings; 145 // TODO: make connection error with HTTP_MALFORMED_FRAME 146 bool _valid = false; 147 Http3ErrorCode _error_code; 148 const char *_error_reason = nullptr; 149 }; 150 151 using Http3FrameDeleterFunc = void (*)(Http3Frame *p); 152 using Http3FrameUPtr = std::unique_ptr<Http3Frame, Http3FrameDeleterFunc>; 153 using Http3DataFrameUPtr = std::unique_ptr<Http3DataFrame, Http3FrameDeleterFunc>; 154 using Http3HeadersFrameUPtr = std::unique_ptr<Http3HeadersFrame, Http3FrameDeleterFunc>; 155 using Http3SettingsFrameUPtr = std::unique_ptr<Http3SettingsFrame, Http3FrameDeleterFunc>; 156 157 using Http3FrameDeleterFunc = void (*)(Http3Frame *p); 158 using Http3FrameUPtr = std::unique_ptr<Http3Frame, Http3FrameDeleterFunc>; 159 using Http3DataFrameUPtr = std::unique_ptr<Http3DataFrame, Http3FrameDeleterFunc>; 160 using Http3HeadersFrameUPtr = std::unique_ptr<Http3HeadersFrame, Http3FrameDeleterFunc>; 161 162 extern ClassAllocator<Http3Frame> http3FrameAllocator; 163 extern ClassAllocator<Http3DataFrame> http3DataFrameAllocator; 164 extern ClassAllocator<Http3HeadersFrame> http3HeadersFrameAllocator; 165 extern ClassAllocator<Http3SettingsFrame> http3SettingsFrameAllocator; 166 167 class Http3FrameDeleter 168 { 169 public: 170 static void delete_null_frame(Http3Frame * frame)171 delete_null_frame(Http3Frame *frame) 172 { 173 ink_assert(frame == nullptr); 174 } 175 176 static void delete_frame(Http3Frame * frame)177 delete_frame(Http3Frame *frame) 178 { 179 frame->~Http3Frame(); 180 http3FrameAllocator.free(static_cast<Http3Frame *>(frame)); 181 } 182 183 static void delete_data_frame(Http3Frame * frame)184 delete_data_frame(Http3Frame *frame) 185 { 186 frame->~Http3Frame(); 187 http3DataFrameAllocator.free(static_cast<Http3DataFrame *>(frame)); 188 } 189 190 static void delete_headers_frame(Http3Frame * frame)191 delete_headers_frame(Http3Frame *frame) 192 { 193 frame->~Http3Frame(); 194 http3HeadersFrameAllocator.free(static_cast<Http3HeadersFrame *>(frame)); 195 } 196 197 static void delete_settings_frame(Http3Frame * frame)198 delete_settings_frame(Http3Frame *frame) 199 { 200 frame->~Http3Frame(); 201 http3SettingsFrameAllocator.free(static_cast<Http3SettingsFrame *>(frame)); 202 } 203 }; 204 205 // 206 // Http3FrameFactory 207 // 208 class Http3FrameFactory 209 { 210 public: 211 /* 212 * This is for an empty Http3FrameUPtr. 213 * Empty frames are used for variable initialization and return value of frame creation failure 214 */ 215 static Http3FrameUPtr create_null_frame(); 216 217 /* 218 * This is used for creating a Http3Frame object based on received data. 219 */ 220 static Http3FrameUPtr create(const uint8_t *buf, size_t len); 221 222 /* 223 * This works almost the same as create() but it reuses created objects for performance. 224 * If you create a frame object which has the same frame type that you created before, the object will be reset by new data. 225 */ 226 std::shared_ptr<const Http3Frame> fast_create(QUICStreamIO &stream_io, size_t frame_len); 227 std::shared_ptr<const Http3Frame> fast_create(const uint8_t *buf, size_t len); 228 229 /* 230 * Creates a HEADERS frame. 231 */ 232 static Http3HeadersFrameUPtr create_headers_frame(const uint8_t *header_block, size_t header_block_len); 233 static Http3HeadersFrameUPtr create_headers_frame(IOBufferReader *header_block_reader, size_t header_block_len); 234 235 /* 236 * Creates a DATA frame. 237 */ 238 static Http3DataFrameUPtr create_data_frame(const uint8_t *data, size_t data_len); 239 static Http3DataFrameUPtr create_data_frame(IOBufferReader *reader, size_t data_len); 240 241 private: 242 std::shared_ptr<Http3Frame> _unknown_frame = nullptr; 243 std::shared_ptr<Http3Frame> _reusable_frames[256] = {nullptr}; 244 }; 245