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 <memory> 27 #include <atomic> 28 #include <cstddef> 29 30 #include "I_IOBuffer.h" 31 32 #include "QUICTypes.h" 33 #include "QUICRetryIntegrityTag.h" 34 35 #define QUIC_FIELD_OFFSET_CONNECTION_ID 1 36 #define QUIC_FIELD_OFFSET_PACKET_NUMBER 4 37 #define QUIC_FIELD_OFFSET_PAYLOAD 5 38 39 class UDPConnection; 40 41 class QUICPacket 42 { 43 public: 44 static constexpr int MAX_INSTANCE_SIZE = 1024; 45 46 // Token field in Initial packet could be very long. 47 static constexpr size_t MAX_PACKET_HEADER_LEN = 256; 48 49 /** 50 * Creates a QUICPacket for sending packets 51 */ 52 QUICPacket(bool ack_eliciting, bool probing); 53 54 virtual ~QUICPacket(); 55 56 virtual QUICPacketType type() const = 0; 57 virtual QUICConnectionId destination_cid() const = 0; 58 virtual QUICPacketNumber packet_number() const = 0; 59 bool is_ack_eliciting() const; 60 bool is_probing_packet() const; 61 62 // TODO These two should be pure virtual 63 virtual Ptr<IOBufferBlock> header_block()64 header_block() const 65 { 66 return Ptr<IOBufferBlock>(); 67 }; 68 virtual Ptr<IOBufferBlock> payload_block()69 payload_block() const 70 { 71 return Ptr<IOBufferBlock>(); 72 }; 73 74 /* 75 * Size of whole QUIC packet (header + payload + integrity check) 76 */ 77 virtual uint16_t size() const; 78 79 /* 80 * Size of header 81 */ 82 virtual uint16_t header_size() const; 83 84 /* 85 * Length of payload (payload + integrity check if exists) 86 */ 87 virtual uint16_t payload_length() const; 88 89 /** 90 * Key phase 91 */ 92 virtual QUICKeyPhase key_phase() const; 93 94 // FIXME Remove this and use IOBufferBlock instead 95 void store(uint8_t *buf, size_t *len) const; 96 97 /***** STATIC MEMBERS *****/ 98 99 static uint8_t calc_packet_number_len(QUICPacketNumber num, QUICPacketNumber base); 100 static bool encode_packet_number(QUICPacketNumber &dst, QUICPacketNumber src, size_t len); 101 static bool decode_packet_number(QUICPacketNumber &dst, QUICPacketNumber src, size_t len, QUICPacketNumber largest_acked); 102 103 protected: 104 QUICPacket(); 105 106 private: 107 bool _is_ack_eliciting = false; 108 bool _is_probing_packet = false; 109 }; 110 111 class QUICPacketR : public QUICPacket 112 { 113 public: 114 /** 115 * Creates a QUICPacket for receiving packets 116 */ 117 QUICPacketR(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to); 118 119 virtual QUICPacketType type() const override = 0; 120 121 UDPConnection *udp_con() const; 122 virtual const IpEndpoint &from() const; 123 virtual const IpEndpoint &to() const; 124 125 static bool read_essential_info(Ptr<IOBufferBlock> block, QUICPacketType &type, QUICVersion &version, QUICConnectionId &dcid, 126 QUICConnectionId &scid, QUICPacketNumber &packet_number, QUICPacketNumber base_packet_number, 127 QUICKeyPhase &key_phase); 128 static bool type(QUICPacketType &type, const uint8_t *packet, size_t packet_len); 129 130 protected: 131 Ptr<IOBufferBlock> _header_block; 132 Ptr<IOBufferBlock> _payload_block; 133 134 private: 135 UDPConnection *_udp_con = nullptr; 136 const IpEndpoint _from = {}; 137 const IpEndpoint _to = {}; 138 }; 139 140 using QUICPacketDeleterFunc = void (*)(QUICPacket *p); 141 using QUICPacketUPtr = std::unique_ptr<QUICPacket, QUICPacketDeleterFunc>; 142 143 class QUICPacketDeleter 144 { 145 public: 146 static void delete_null_packet(QUICPacket * packet)147 delete_null_packet(QUICPacket *packet) 148 { 149 ink_assert(packet == nullptr); 150 } 151 152 static void delete_dont_free(QUICPacket * packet)153 delete_dont_free(QUICPacket *packet) 154 { 155 packet->~QUICPacket(); 156 } 157 158 static void delete_packet_new(QUICPacket * packet)159 delete_packet_new(QUICPacket *packet) 160 { 161 delete packet; 162 } 163 }; 164 165 class QUICLongHeaderPacket : public QUICPacket 166 { 167 public: 168 /** 169 * For sending packet 170 */ 171 QUICLongHeaderPacket(QUICVersion version, const QUICConnectionId &dcid, const QUICConnectionId &scid, bool ack_eliciting, 172 bool probing, bool crypto); 173 174 QUICConnectionId source_cid() const; 175 176 QUICConnectionId destination_cid() const override; 177 uint16_t payload_length() const override; 178 virtual QUICVersion version() const; 179 virtual bool is_crypto_packet() const; 180 181 protected: 182 size_t _write_common_header(uint8_t *buf) const; 183 184 Ptr<IOBufferBlock> _payload_block; 185 size_t _payload_length = 0; 186 187 private: 188 QUICVersion _version; 189 QUICConnectionId _dcid; 190 QUICConnectionId _scid; 191 192 bool _is_crypto_packet; 193 }; 194 195 class QUICLongHeaderPacketR : public QUICPacketR 196 { 197 public: 198 /** 199 * For receiving packet 200 */ 201 QUICLongHeaderPacketR(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, Ptr<IOBufferBlock> blocks); 202 ~QUICLongHeaderPacketR()203 virtual ~QUICLongHeaderPacketR(){}; 204 205 QUICConnectionId destination_cid() const override; 206 QUICConnectionId source_cid() const; 207 virtual QUICVersion version() const; 208 209 static bool type(QUICPacketType &type, const uint8_t *packet, size_t packet_len); 210 static bool version(QUICVersion &version, const uint8_t *packet, size_t packet_len); 211 static bool key_phase(QUICKeyPhase &key_phase, const uint8_t *packet, size_t packet_len); 212 static bool length(size_t &length, uint8_t &length_field_len, size_t &length_field_offset, const uint8_t *packet, 213 size_t packet_len); 214 static bool packet_length(size_t &packet_len, const uint8_t *buf, size_t buf_len); 215 static bool packet_number_offset(size_t &pn_offset, const uint8_t *packet, size_t packet_len); 216 217 protected: 218 QUICVersion _version; 219 QUICConnectionId _scid; 220 QUICConnectionId _dcid; 221 }; 222 223 class QUICShortHeaderPacket : public QUICPacket 224 { 225 public: 226 /** 227 * For sending packet 228 */ 229 QUICShortHeaderPacket(const QUICConnectionId &dcid, QUICPacketNumber packet_number, QUICPacketNumber base_packet_number, 230 QUICKeyPhase key_phase, bool ack_eliciting, bool probing); 231 232 QUICPacketType type() const override; 233 QUICKeyPhase key_phase() const override; 234 QUICPacketNumber packet_number() const override; 235 QUICConnectionId destination_cid() const override; 236 237 uint16_t payload_length() const override; 238 Ptr<IOBufferBlock> header_block() const override; 239 Ptr<IOBufferBlock> payload_block() const override; 240 241 void attach_payload(Ptr<IOBufferBlock> payload, bool unprotected); 242 243 private: 244 QUICConnectionId _dcid; 245 QUICPacketNumber _packet_number; 246 QUICKeyPhase _key_phase; 247 int _packet_number_len; 248 249 Ptr<IOBufferBlock> _payload_block; 250 size_t _payload_length; 251 }; 252 253 class QUICShortHeaderPacketR : public QUICPacketR 254 { 255 public: 256 /** 257 * For receiving packet 258 */ 259 QUICShortHeaderPacketR(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, Ptr<IOBufferBlock> blocks, 260 QUICPacketNumber base_packet_number); 261 262 void attach_payload(Ptr<IOBufferBlock> payload, bool unprotected); 263 264 QUICPacketType type() const override; 265 QUICKeyPhase key_phase() const override; 266 QUICPacketNumber packet_number() const override; 267 QUICConnectionId destination_cid() const override; 268 269 Ptr<IOBufferBlock> header_block() const override; 270 Ptr<IOBufferBlock> payload_block() const override; 271 272 static bool packet_number_offset(size_t &pn_offset, const uint8_t *packet, size_t packet_len, int dcil); 273 274 private: 275 QUICKeyPhase _key_phase; 276 QUICPacketNumber _packet_number; 277 int _packet_number_len; 278 QUICConnectionId _dcid; 279 }; 280 281 class QUICStatelessResetPacket : public QUICPacket 282 { 283 public: 284 /** 285 * For sending packet 286 */ 287 QUICStatelessResetPacket(QUICStatelessResetToken token, size_t maximum_size); 288 289 QUICPacketType type() const override; 290 QUICPacketNumber packet_number() const override; 291 QUICConnectionId destination_cid() const override; 292 293 Ptr<IOBufferBlock> header_block() const override; 294 Ptr<IOBufferBlock> payload_block() const override; 295 296 QUICStatelessResetToken token() const; 297 298 private: 299 QUICStatelessResetToken _token; 300 size_t _maximum_size; 301 }; 302 303 class QUICStatelessResetPacketR : public QUICPacketR 304 { 305 public: 306 /** 307 * For receiving packet 308 */ 309 QUICStatelessResetPacketR(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, Ptr<IOBufferBlock> blocks); 310 311 QUICPacketType type() const override; 312 QUICPacketNumber packet_number() const override; 313 QUICConnectionId destination_cid() const override; 314 }; 315 316 class QUICVersionNegotiationPacket : public QUICLongHeaderPacket 317 { 318 public: 319 /** 320 * For sending packet 321 */ 322 QUICVersionNegotiationPacket(const QUICConnectionId &dcid, const QUICConnectionId &scid, const QUICVersion versions[], 323 int nversions, QUICVersion version_in_initial); 324 325 QUICPacketType type() const override; 326 QUICVersion version() const override; 327 QUICPacketNumber packet_number() const override; 328 uint16_t payload_length() const override; 329 330 Ptr<IOBufferBlock> header_block() const override; 331 Ptr<IOBufferBlock> payload_block() const override; 332 333 const QUICVersion *versions() const; 334 int nversions() const; 335 336 private: 337 const QUICVersion *_versions; 338 int _nversions; 339 const QUICVersion _version_in_initial; 340 }; 341 342 class QUICVersionNegotiationPacketR : public QUICLongHeaderPacketR 343 { 344 public: 345 /** 346 * For receiving packet 347 */ 348 QUICVersionNegotiationPacketR(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, Ptr<IOBufferBlock> blocks); 349 350 QUICPacketType type() const override; 351 QUICPacketNumber packet_number() const override; 352 QUICConnectionId destination_cid() const override; 353 354 Ptr<IOBufferBlock> header_block() const override; 355 Ptr<IOBufferBlock> payload_block() const override; 356 357 const QUICVersion supported_version(uint8_t index) const; 358 int nversions() const; 359 360 private: 361 QUICConnectionId _dcid; 362 uint8_t *_versions; 363 int _nversions; 364 }; 365 366 class QUICInitialPacket : public QUICLongHeaderPacket 367 { 368 public: 369 /** 370 * For sending packet 371 */ 372 QUICInitialPacket(QUICVersion version, const QUICConnectionId &dcid, const QUICConnectionId &scid, size_t token_len, 373 ats_unique_buf token, size_t length, QUICPacketNumber packet_number, bool ack_eliciting, bool probing, 374 bool crypto); 375 376 QUICPacketType type() const override; 377 QUICPacketNumber packet_number() const override; 378 QUICKeyPhase key_phase() const override; 379 380 Ptr<IOBufferBlock> header_block() const override; 381 Ptr<IOBufferBlock> payload_block() const override; 382 void attach_payload(Ptr<IOBufferBlock> payload, bool unprotected); 383 384 private: 385 size_t _token_len = 0; 386 ats_unique_buf _token = ats_unique_buf(nullptr); 387 QUICPacketNumber _packet_number; 388 }; 389 390 class QUICInitialPacketR : public QUICLongHeaderPacketR 391 { 392 public: 393 /** 394 * For receiving packet 395 */ 396 QUICInitialPacketR(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, Ptr<IOBufferBlock> blocks, 397 QUICPacketNumber base_packet_number); 398 ~QUICInitialPacketR(); 399 400 Ptr<IOBufferBlock> header_block() const override; 401 Ptr<IOBufferBlock> payload_block() const override; 402 void attach_payload(Ptr<IOBufferBlock> payload, bool unprotected); 403 404 QUICPacketType type() const override; 405 QUICPacketNumber packet_number() const override; 406 QUICKeyPhase key_phase() const override; 407 408 const QUICAddressValidationToken &token() const; 409 410 static bool token_length(size_t &token_length, uint8_t &field_len, size_t &token_length_filed_offset, const uint8_t *packet, 411 size_t packet_len); 412 413 protected: 414 Ptr<IOBufferBlock> _payload_block; 415 416 private: 417 QUICPacketNumber _packet_number; 418 QUICAddressValidationToken *_token = nullptr; 419 420 bool _parse(); 421 }; 422 423 class QUICZeroRttPacket : public QUICLongHeaderPacket 424 { 425 public: 426 /** 427 * For sending packet 428 */ 429 QUICZeroRttPacket(QUICVersion version, const QUICConnectionId &dcid, const QUICConnectionId &scid, size_t length, 430 QUICPacketNumber packet_number, bool ack_eliciting, bool probing); 431 432 QUICPacketType type() const override; 433 QUICPacketNumber packet_number() const override; 434 QUICKeyPhase key_phase() const override; 435 436 Ptr<IOBufferBlock> header_block() const override; 437 Ptr<IOBufferBlock> payload_block() const override; 438 void attach_payload(Ptr<IOBufferBlock> payload, bool unprotected); 439 440 private: 441 QUICPacketNumber _packet_number; 442 }; 443 444 class QUICZeroRttPacketR : public QUICLongHeaderPacketR 445 { 446 public: 447 /** 448 * For receiving packet 449 */ 450 QUICZeroRttPacketR(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, Ptr<IOBufferBlock> blocks, 451 QUICPacketNumber base_packet_number); 452 453 Ptr<IOBufferBlock> header_block() const override; 454 Ptr<IOBufferBlock> payload_block() const override; 455 void attach_payload(Ptr<IOBufferBlock> payload, bool unprotected); 456 457 QUICPacketType type() const override; 458 QUICPacketNumber packet_number() const override; 459 QUICKeyPhase key_phase() const override; 460 461 private: 462 QUICPacketNumber _packet_number; 463 }; 464 465 class QUICHandshakePacket : public QUICLongHeaderPacket 466 { 467 public: 468 /** 469 * For sending packet 470 */ 471 QUICHandshakePacket(QUICVersion version, const QUICConnectionId &dcid, const QUICConnectionId &scid, size_t length, 472 QUICPacketNumber packet_number, bool ack_eliciting, bool probing, bool crypto); 473 474 QUICPacketType type() const override; 475 QUICKeyPhase key_phase() const override; 476 QUICPacketNumber packet_number() const override; 477 478 Ptr<IOBufferBlock> header_block() const override; 479 Ptr<IOBufferBlock> payload_block() const override; 480 void attach_payload(Ptr<IOBufferBlock> payload, bool unprotected); 481 482 private: 483 QUICPacketNumber _packet_number; 484 }; 485 486 class QUICHandshakePacketR : public QUICLongHeaderPacketR 487 { 488 public: 489 /** 490 * For receiving packet 491 */ 492 QUICHandshakePacketR(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, Ptr<IOBufferBlock> blocks, 493 QUICPacketNumber base_packet_number); 494 495 Ptr<IOBufferBlock> header_block() const override; 496 Ptr<IOBufferBlock> payload_block() const override; 497 void attach_payload(Ptr<IOBufferBlock> payload, bool unprotected); 498 499 QUICPacketType type() const override; 500 QUICKeyPhase key_phase() const override; 501 QUICPacketNumber packet_number() const override; 502 503 private: 504 QUICPacketNumber _packet_number; 505 }; 506 507 class QUICRetryPacket : public QUICLongHeaderPacket 508 { 509 public: 510 /** 511 * For sending packet 512 */ 513 QUICRetryPacket(QUICVersion version, const QUICConnectionId &dcid, const QUICConnectionId &scid, QUICRetryToken &token); 514 515 QUICPacketType type() const override; 516 QUICPacketNumber packet_number() const override; 517 uint16_t payload_length() const override; 518 519 Ptr<IOBufferBlock> header_block() const override; 520 Ptr<IOBufferBlock> payload_block() const override; 521 522 const QUICRetryToken &token() const; 523 524 private: 525 QUICRetryToken _token; 526 527 bool _compute_retry_integrity_tag(uint8_t *out, QUICConnectionId odcid, Ptr<IOBufferBlock> header, 528 Ptr<IOBufferBlock> payload) const; 529 }; 530 531 class QUICRetryPacketR : public QUICLongHeaderPacketR 532 { 533 public: 534 /** 535 * For receiving packet 536 */ 537 QUICRetryPacketR(UDPConnection *udp_con, IpEndpoint from, IpEndpoint to, Ptr<IOBufferBlock> blocks); 538 ~QUICRetryPacketR(); 539 540 Ptr<IOBufferBlock> header_block() const override; 541 Ptr<IOBufferBlock> payload_block() const override; 542 543 QUICPacketType type() const override; 544 QUICPacketNumber packet_number() const override; 545 546 const QUICAddressValidationToken &token() const; 547 bool has_valid_tag(const QUICConnectionId &odcid) const; 548 549 private: 550 QUICAddressValidationToken *_token = nullptr; 551 uint8_t _integrity_tag[QUICRetryIntegrityTag::LEN]; 552 Ptr<IOBufferBlock> _payload_block_without_tag; 553 }; 554