github.com/metacubex/quic-go@v0.44.1-0.20240520163451-20b689a59136/packet_packer.go (about) 1 package quic 2 3 import ( 4 crand "crypto/rand" 5 "encoding/binary" 6 "errors" 7 "fmt" 8 9 "golang.org/x/exp/rand" 10 11 "github.com/metacubex/quic-go/internal/ackhandler" 12 "github.com/metacubex/quic-go/internal/handshake" 13 "github.com/metacubex/quic-go/internal/protocol" 14 "github.com/metacubex/quic-go/internal/qerr" 15 "github.com/metacubex/quic-go/internal/wire" 16 ) 17 18 var errNothingToPack = errors.New("nothing to pack") 19 20 type packer interface { 21 PackCoalescedPacket(onlyAck bool, maxPacketSize protocol.ByteCount, v protocol.Version) (*coalescedPacket, error) 22 PackAckOnlyPacket(maxPacketSize protocol.ByteCount, v protocol.Version) (shortHeaderPacket, *packetBuffer, error) 23 AppendPacket(buf *packetBuffer, maxPacketSize protocol.ByteCount, v protocol.Version) (shortHeaderPacket, error) 24 MaybePackProbePacket(protocol.EncryptionLevel, protocol.ByteCount, protocol.Version) (*coalescedPacket, error) 25 PackConnectionClose(*qerr.TransportError, protocol.ByteCount, protocol.Version) (*coalescedPacket, error) 26 PackApplicationClose(*qerr.ApplicationError, protocol.ByteCount, protocol.Version) (*coalescedPacket, error) 27 PackMTUProbePacket(ping ackhandler.Frame, size protocol.ByteCount, v protocol.Version) (shortHeaderPacket, *packetBuffer, error) 28 29 SetToken([]byte) 30 } 31 32 type sealer interface { 33 handshake.LongHeaderSealer 34 } 35 36 type payload struct { 37 streamFrames []ackhandler.StreamFrame 38 frames []ackhandler.Frame 39 ack *wire.AckFrame 40 length protocol.ByteCount 41 } 42 43 type longHeaderPacket struct { 44 header *wire.ExtendedHeader 45 ack *wire.AckFrame 46 frames []ackhandler.Frame 47 streamFrames []ackhandler.StreamFrame // only used for 0-RTT packets 48 49 length protocol.ByteCount 50 } 51 52 type shortHeaderPacket struct { 53 PacketNumber protocol.PacketNumber 54 Frames []ackhandler.Frame 55 StreamFrames []ackhandler.StreamFrame 56 Ack *wire.AckFrame 57 Length protocol.ByteCount 58 IsPathMTUProbePacket bool 59 60 // used for logging 61 DestConnID protocol.ConnectionID 62 PacketNumberLen protocol.PacketNumberLen 63 KeyPhase protocol.KeyPhaseBit 64 } 65 66 func (p *shortHeaderPacket) IsAckEliciting() bool { return ackhandler.HasAckElicitingFrames(p.Frames) } 67 68 type coalescedPacket struct { 69 buffer *packetBuffer 70 longHdrPackets []*longHeaderPacket 71 shortHdrPacket *shortHeaderPacket 72 } 73 74 // IsOnlyShortHeaderPacket says if this packet only contains a short header packet (and no long header packets). 75 func (p *coalescedPacket) IsOnlyShortHeaderPacket() bool { 76 return len(p.longHdrPackets) == 0 && p.shortHdrPacket != nil 77 } 78 79 func (p *longHeaderPacket) EncryptionLevel() protocol.EncryptionLevel { 80 //nolint:exhaustive // Will never be called for Retry packets (and they don't have encrypted data). 81 switch p.header.Type { 82 case protocol.PacketTypeInitial: 83 return protocol.EncryptionInitial 84 case protocol.PacketTypeHandshake: 85 return protocol.EncryptionHandshake 86 case protocol.PacketType0RTT: 87 return protocol.Encryption0RTT 88 default: 89 panic("can't determine encryption level") 90 } 91 } 92 93 func (p *longHeaderPacket) IsAckEliciting() bool { return ackhandler.HasAckElicitingFrames(p.frames) } 94 95 type packetNumberManager interface { 96 PeekPacketNumber(protocol.EncryptionLevel) (protocol.PacketNumber, protocol.PacketNumberLen) 97 PopPacketNumber(protocol.EncryptionLevel) protocol.PacketNumber 98 } 99 100 type sealingManager interface { 101 GetInitialSealer() (handshake.LongHeaderSealer, error) 102 GetHandshakeSealer() (handshake.LongHeaderSealer, error) 103 Get0RTTSealer() (handshake.LongHeaderSealer, error) 104 Get1RTTSealer() (handshake.ShortHeaderSealer, error) 105 } 106 107 type frameSource interface { 108 HasData() bool 109 AppendStreamFrames([]ackhandler.StreamFrame, protocol.ByteCount, protocol.Version) ([]ackhandler.StreamFrame, protocol.ByteCount) 110 AppendControlFrames([]ackhandler.Frame, protocol.ByteCount, protocol.Version) ([]ackhandler.Frame, protocol.ByteCount) 111 } 112 113 type ackFrameSource interface { 114 GetAckFrame(encLevel protocol.EncryptionLevel, onlyIfQueued bool) *wire.AckFrame 115 } 116 117 type packetPacker struct { 118 srcConnID protocol.ConnectionID 119 getDestConnID func() protocol.ConnectionID 120 121 perspective protocol.Perspective 122 cryptoSetup sealingManager 123 124 initialStream cryptoStream 125 handshakeStream cryptoStream 126 127 token []byte 128 129 pnManager packetNumberManager 130 framer frameSource 131 acks ackFrameSource 132 datagramQueue *datagramQueue 133 retransmissionQueue *retransmissionQueue 134 rand rand.Rand 135 136 numNonAckElicitingAcks int 137 138 peekTimes int 139 } 140 141 const DatagramFrameMaxPeekTimes = 10 142 143 var _ packer = &packetPacker{} 144 145 func newPacketPacker( 146 srcConnID protocol.ConnectionID, 147 getDestConnID func() protocol.ConnectionID, 148 initialStream, handshakeStream cryptoStream, 149 packetNumberManager packetNumberManager, 150 retransmissionQueue *retransmissionQueue, 151 cryptoSetup sealingManager, 152 framer frameSource, 153 acks ackFrameSource, 154 datagramQueue *datagramQueue, 155 perspective protocol.Perspective, 156 ) *packetPacker { 157 var b [8]byte 158 _, _ = crand.Read(b[:]) 159 160 return &packetPacker{ 161 cryptoSetup: cryptoSetup, 162 getDestConnID: getDestConnID, 163 srcConnID: srcConnID, 164 initialStream: initialStream, 165 handshakeStream: handshakeStream, 166 retransmissionQueue: retransmissionQueue, 167 datagramQueue: datagramQueue, 168 perspective: perspective, 169 framer: framer, 170 acks: acks, 171 rand: *rand.New(rand.NewSource(binary.BigEndian.Uint64(b[:]))), 172 pnManager: packetNumberManager, 173 } 174 } 175 176 // PackConnectionClose packs a packet that closes the connection with a transport error. 177 func (p *packetPacker) PackConnectionClose(e *qerr.TransportError, maxPacketSize protocol.ByteCount, v protocol.Version) (*coalescedPacket, error) { 178 var reason string 179 // don't send details of crypto errors 180 if !e.ErrorCode.IsCryptoError() { 181 reason = e.ErrorMessage 182 } 183 return p.packConnectionClose(false, uint64(e.ErrorCode), e.FrameType, reason, maxPacketSize, v) 184 } 185 186 // PackApplicationClose packs a packet that closes the connection with an application error. 187 func (p *packetPacker) PackApplicationClose(e *qerr.ApplicationError, maxPacketSize protocol.ByteCount, v protocol.Version) (*coalescedPacket, error) { 188 return p.packConnectionClose(true, uint64(e.ErrorCode), 0, e.ErrorMessage, maxPacketSize, v) 189 } 190 191 func (p *packetPacker) packConnectionClose( 192 isApplicationError bool, 193 errorCode uint64, 194 frameType uint64, 195 reason string, 196 maxPacketSize protocol.ByteCount, 197 v protocol.Version, 198 ) (*coalescedPacket, error) { 199 var sealers [4]sealer 200 var hdrs [3]*wire.ExtendedHeader 201 var payloads [4]payload 202 var size protocol.ByteCount 203 var connID protocol.ConnectionID 204 var oneRTTPacketNumber protocol.PacketNumber 205 var oneRTTPacketNumberLen protocol.PacketNumberLen 206 var keyPhase protocol.KeyPhaseBit // only set for 1-RTT 207 var numLongHdrPackets uint8 208 encLevels := [4]protocol.EncryptionLevel{protocol.EncryptionInitial, protocol.EncryptionHandshake, protocol.Encryption0RTT, protocol.Encryption1RTT} 209 for i, encLevel := range encLevels { 210 if p.perspective == protocol.PerspectiveServer && encLevel == protocol.Encryption0RTT { 211 continue 212 } 213 ccf := &wire.ConnectionCloseFrame{ 214 IsApplicationError: isApplicationError, 215 ErrorCode: errorCode, 216 FrameType: frameType, 217 ReasonPhrase: reason, 218 } 219 // don't send application errors in Initial or Handshake packets 220 if isApplicationError && (encLevel == protocol.EncryptionInitial || encLevel == protocol.EncryptionHandshake) { 221 ccf.IsApplicationError = false 222 ccf.ErrorCode = uint64(qerr.ApplicationErrorErrorCode) 223 ccf.ReasonPhrase = "" 224 } 225 pl := payload{ 226 frames: []ackhandler.Frame{{Frame: ccf}}, 227 length: ccf.Length(v), 228 } 229 230 var sealer sealer 231 var err error 232 switch encLevel { 233 case protocol.EncryptionInitial: 234 sealer, err = p.cryptoSetup.GetInitialSealer() 235 case protocol.EncryptionHandshake: 236 sealer, err = p.cryptoSetup.GetHandshakeSealer() 237 case protocol.Encryption0RTT: 238 sealer, err = p.cryptoSetup.Get0RTTSealer() 239 case protocol.Encryption1RTT: 240 var s handshake.ShortHeaderSealer 241 s, err = p.cryptoSetup.Get1RTTSealer() 242 if err == nil { 243 keyPhase = s.KeyPhase() 244 } 245 sealer = s 246 } 247 if err == handshake.ErrKeysNotYetAvailable || err == handshake.ErrKeysDropped { 248 continue 249 } 250 if err != nil { 251 return nil, err 252 } 253 sealers[i] = sealer 254 var hdr *wire.ExtendedHeader 255 if encLevel == protocol.Encryption1RTT { 256 connID = p.getDestConnID() 257 oneRTTPacketNumber, oneRTTPacketNumberLen = p.pnManager.PeekPacketNumber(protocol.Encryption1RTT) 258 size += p.shortHeaderPacketLength(connID, oneRTTPacketNumberLen, pl) 259 } else { 260 hdr = p.getLongHeader(encLevel, v) 261 hdrs[i] = hdr 262 size += p.longHeaderPacketLength(hdr, pl, v) + protocol.ByteCount(sealer.Overhead()) 263 numLongHdrPackets++ 264 } 265 payloads[i] = pl 266 } 267 buffer := getPacketBuffer() 268 packet := &coalescedPacket{ 269 buffer: buffer, 270 longHdrPackets: make([]*longHeaderPacket, 0, numLongHdrPackets), 271 } 272 for i, encLevel := range encLevels { 273 if sealers[i] == nil { 274 continue 275 } 276 var paddingLen protocol.ByteCount 277 if encLevel == protocol.EncryptionInitial { 278 paddingLen = p.initialPaddingLen(payloads[i].frames, size, maxPacketSize) 279 } 280 if encLevel == protocol.Encryption1RTT { 281 shp, err := p.appendShortHeaderPacket(buffer, connID, oneRTTPacketNumber, oneRTTPacketNumberLen, keyPhase, payloads[i], paddingLen, maxPacketSize, sealers[i], false, v) 282 if err != nil { 283 return nil, err 284 } 285 packet.shortHdrPacket = &shp 286 } else { 287 longHdrPacket, err := p.appendLongHeaderPacket(buffer, hdrs[i], payloads[i], paddingLen, encLevel, sealers[i], v) 288 if err != nil { 289 buffer.Release() 290 return nil, err 291 } 292 packet.longHdrPackets = append(packet.longHdrPackets, longHdrPacket) 293 } 294 } 295 return packet, nil 296 } 297 298 // longHeaderPacketLength calculates the length of a serialized long header packet. 299 // It takes into account that packets that have a tiny payload need to be padded, 300 // such that len(payload) + packet number len >= 4 + AEAD overhead 301 func (p *packetPacker) longHeaderPacketLength(hdr *wire.ExtendedHeader, pl payload, v protocol.Version) protocol.ByteCount { 302 var paddingLen protocol.ByteCount 303 pnLen := protocol.ByteCount(hdr.PacketNumberLen) 304 if pl.length < 4-pnLen { 305 paddingLen = 4 - pnLen - pl.length 306 } 307 return hdr.GetLength(v) + pl.length + paddingLen 308 } 309 310 // shortHeaderPacketLength calculates the length of a serialized short header packet. 311 // It takes into account that packets that have a tiny payload need to be padded, 312 // such that len(payload) + packet number len >= 4 + AEAD overhead 313 func (p *packetPacker) shortHeaderPacketLength(connID protocol.ConnectionID, pnLen protocol.PacketNumberLen, pl payload) protocol.ByteCount { 314 var paddingLen protocol.ByteCount 315 if pl.length < 4-protocol.ByteCount(pnLen) { 316 paddingLen = 4 - protocol.ByteCount(pnLen) - pl.length 317 } 318 return wire.ShortHeaderLen(connID, pnLen) + pl.length + paddingLen 319 } 320 321 // size is the expected size of the packet, if no padding was applied. 322 func (p *packetPacker) initialPaddingLen(frames []ackhandler.Frame, currentSize, maxPacketSize protocol.ByteCount) protocol.ByteCount { 323 // For the server, only ack-eliciting Initial packets need to be padded. 324 if p.perspective == protocol.PerspectiveServer && !ackhandler.HasAckElicitingFrames(frames) { 325 return 0 326 } 327 if currentSize >= maxPacketSize { 328 return 0 329 } 330 return maxPacketSize - currentSize 331 } 332 333 // PackCoalescedPacket packs a new packet. 334 // It packs an Initial / Handshake if there is data to send in these packet number spaces. 335 // It should only be called before the handshake is confirmed. 336 func (p *packetPacker) PackCoalescedPacket(onlyAck bool, maxPacketSize protocol.ByteCount, v protocol.Version) (*coalescedPacket, error) { 337 var ( 338 initialHdr, handshakeHdr, zeroRTTHdr *wire.ExtendedHeader 339 initialPayload, handshakePayload, zeroRTTPayload, oneRTTPayload payload 340 oneRTTPacketNumber protocol.PacketNumber 341 oneRTTPacketNumberLen protocol.PacketNumberLen 342 ) 343 // Try packing an Initial packet. 344 initialSealer, err := p.cryptoSetup.GetInitialSealer() 345 if err != nil && err != handshake.ErrKeysDropped { 346 return nil, err 347 } 348 var size protocol.ByteCount 349 if initialSealer != nil { 350 initialHdr, initialPayload = p.maybeGetCryptoPacket(maxPacketSize-protocol.ByteCount(initialSealer.Overhead()), protocol.EncryptionInitial, onlyAck, true, v) 351 if initialPayload.length > 0 { 352 size += p.longHeaderPacketLength(initialHdr, initialPayload, v) + protocol.ByteCount(initialSealer.Overhead()) 353 } 354 } 355 356 // Add a Handshake packet. 357 var handshakeSealer sealer 358 if (onlyAck && size == 0) || (!onlyAck && size < maxPacketSize-protocol.MinCoalescedPacketSize) { 359 var err error 360 handshakeSealer, err = p.cryptoSetup.GetHandshakeSealer() 361 if err != nil && err != handshake.ErrKeysDropped && err != handshake.ErrKeysNotYetAvailable { 362 return nil, err 363 } 364 if handshakeSealer != nil { 365 handshakeHdr, handshakePayload = p.maybeGetCryptoPacket(maxPacketSize-size-protocol.ByteCount(handshakeSealer.Overhead()), protocol.EncryptionHandshake, onlyAck, size == 0, v) 366 if handshakePayload.length > 0 { 367 s := p.longHeaderPacketLength(handshakeHdr, handshakePayload, v) + protocol.ByteCount(handshakeSealer.Overhead()) 368 size += s 369 } 370 } 371 } 372 373 // Add a 0-RTT / 1-RTT packet. 374 var zeroRTTSealer sealer 375 var oneRTTSealer handshake.ShortHeaderSealer 376 var connID protocol.ConnectionID 377 var kp protocol.KeyPhaseBit 378 if (onlyAck && size == 0) || (!onlyAck && size < maxPacketSize-protocol.MinCoalescedPacketSize) { 379 var err error 380 oneRTTSealer, err = p.cryptoSetup.Get1RTTSealer() 381 if err != nil && err != handshake.ErrKeysDropped && err != handshake.ErrKeysNotYetAvailable { 382 return nil, err 383 } 384 if err == nil { // 1-RTT 385 kp = oneRTTSealer.KeyPhase() 386 connID = p.getDestConnID() 387 oneRTTPacketNumber, oneRTTPacketNumberLen = p.pnManager.PeekPacketNumber(protocol.Encryption1RTT) 388 hdrLen := wire.ShortHeaderLen(connID, oneRTTPacketNumberLen) 389 oneRTTPayload = p.maybeGetShortHeaderPacket(oneRTTSealer, hdrLen, maxPacketSize-size, onlyAck, size == 0, v) 390 if oneRTTPayload.length > 0 { 391 size += p.shortHeaderPacketLength(connID, oneRTTPacketNumberLen, oneRTTPayload) + protocol.ByteCount(oneRTTSealer.Overhead()) 392 } 393 } else if p.perspective == protocol.PerspectiveClient && !onlyAck { // 0-RTT packets can't contain ACK frames 394 var err error 395 zeroRTTSealer, err = p.cryptoSetup.Get0RTTSealer() 396 if err != nil && err != handshake.ErrKeysDropped && err != handshake.ErrKeysNotYetAvailable { 397 return nil, err 398 } 399 if zeroRTTSealer != nil { 400 zeroRTTHdr, zeroRTTPayload = p.maybeGetAppDataPacketFor0RTT(zeroRTTSealer, maxPacketSize-size, v) 401 if zeroRTTPayload.length > 0 { 402 size += p.longHeaderPacketLength(zeroRTTHdr, zeroRTTPayload, v) + protocol.ByteCount(zeroRTTSealer.Overhead()) 403 } 404 } 405 } 406 } 407 408 if initialPayload.length == 0 && handshakePayload.length == 0 && zeroRTTPayload.length == 0 && oneRTTPayload.length == 0 { 409 return nil, nil 410 } 411 412 buffer := getPacketBuffer() 413 packet := &coalescedPacket{ 414 buffer: buffer, 415 longHdrPackets: make([]*longHeaderPacket, 0, 3), 416 } 417 if initialPayload.length > 0 { 418 padding := p.initialPaddingLen(initialPayload.frames, size, maxPacketSize) 419 cont, err := p.appendLongHeaderPacket(buffer, initialHdr, initialPayload, padding, protocol.EncryptionInitial, initialSealer, v) 420 if err != nil { 421 buffer.Release() 422 return nil, err 423 } 424 packet.longHdrPackets = append(packet.longHdrPackets, cont) 425 } 426 if handshakePayload.length > 0 { 427 cont, err := p.appendLongHeaderPacket(buffer, handshakeHdr, handshakePayload, 0, protocol.EncryptionHandshake, handshakeSealer, v) 428 if err != nil { 429 buffer.Release() 430 return nil, err 431 } 432 packet.longHdrPackets = append(packet.longHdrPackets, cont) 433 } 434 if zeroRTTPayload.length > 0 { 435 longHdrPacket, err := p.appendLongHeaderPacket(buffer, zeroRTTHdr, zeroRTTPayload, 0, protocol.Encryption0RTT, zeroRTTSealer, v) 436 if err != nil { 437 buffer.Release() 438 return nil, err 439 } 440 packet.longHdrPackets = append(packet.longHdrPackets, longHdrPacket) 441 } else if oneRTTPayload.length > 0 { 442 shp, err := p.appendShortHeaderPacket(buffer, connID, oneRTTPacketNumber, oneRTTPacketNumberLen, kp, oneRTTPayload, 0, maxPacketSize, oneRTTSealer, false, v) 443 if err != nil { 444 buffer.Release() 445 return nil, err 446 } 447 packet.shortHdrPacket = &shp 448 } 449 return packet, nil 450 } 451 452 // PackAckOnlyPacket packs a packet containing only an ACK in the application data packet number space. 453 // It should be called after the handshake is confirmed. 454 func (p *packetPacker) PackAckOnlyPacket(maxPacketSize protocol.ByteCount, v protocol.Version) (shortHeaderPacket, *packetBuffer, error) { 455 buf := getPacketBuffer() 456 packet, err := p.appendPacket(buf, true, maxPacketSize, v) 457 return packet, buf, err 458 } 459 460 // AppendPacket packs a packet in the application data packet number space. 461 // It should be called after the handshake is confirmed. 462 func (p *packetPacker) AppendPacket(buf *packetBuffer, maxPacketSize protocol.ByteCount, v protocol.Version) (shortHeaderPacket, error) { 463 return p.appendPacket(buf, false, maxPacketSize, v) 464 } 465 466 func (p *packetPacker) appendPacket(buf *packetBuffer, onlyAck bool, maxPacketSize protocol.ByteCount, v protocol.Version) (shortHeaderPacket, error) { 467 sealer, err := p.cryptoSetup.Get1RTTSealer() 468 if err != nil { 469 return shortHeaderPacket{}, err 470 } 471 pn, pnLen := p.pnManager.PeekPacketNumber(protocol.Encryption1RTT) 472 connID := p.getDestConnID() 473 hdrLen := wire.ShortHeaderLen(connID, pnLen) 474 pl := p.maybeGetShortHeaderPacket(sealer, hdrLen, maxPacketSize, onlyAck, true, v) 475 if pl.length == 0 { 476 return shortHeaderPacket{}, errNothingToPack 477 } 478 kp := sealer.KeyPhase() 479 480 return p.appendShortHeaderPacket(buf, connID, pn, pnLen, kp, pl, 0, maxPacketSize, sealer, false, v) 481 } 482 483 func (p *packetPacker) maybeGetCryptoPacket(maxPacketSize protocol.ByteCount, encLevel protocol.EncryptionLevel, onlyAck, ackAllowed bool, v protocol.Version) (*wire.ExtendedHeader, payload) { 484 if onlyAck { 485 if ack := p.acks.GetAckFrame(encLevel, true); ack != nil { 486 return p.getLongHeader(encLevel, v), payload{ 487 ack: ack, 488 length: ack.Length(v), 489 } 490 } 491 return nil, payload{} 492 } 493 494 var s cryptoStream 495 var handler ackhandler.FrameHandler 496 var hasRetransmission bool 497 //nolint:exhaustive // Initial and Handshake are the only two encryption levels here. 498 switch encLevel { 499 case protocol.EncryptionInitial: 500 s = p.initialStream 501 handler = p.retransmissionQueue.InitialAckHandler() 502 hasRetransmission = p.retransmissionQueue.HasInitialData() 503 case protocol.EncryptionHandshake: 504 s = p.handshakeStream 505 handler = p.retransmissionQueue.HandshakeAckHandler() 506 hasRetransmission = p.retransmissionQueue.HasHandshakeData() 507 } 508 509 hasData := s.HasData() 510 var ack *wire.AckFrame 511 if ackAllowed { 512 ack = p.acks.GetAckFrame(encLevel, !hasRetransmission && !hasData) 513 } 514 if !hasData && !hasRetransmission && ack == nil { 515 // nothing to send 516 return nil, payload{} 517 } 518 519 var pl payload 520 if ack != nil { 521 pl.ack = ack 522 pl.length = ack.Length(v) 523 maxPacketSize -= pl.length 524 } 525 hdr := p.getLongHeader(encLevel, v) 526 maxPacketSize -= hdr.GetLength(v) 527 if hasRetransmission { 528 for { 529 var f ackhandler.Frame 530 //nolint:exhaustive // 0-RTT packets can't contain any retransmission.s 531 switch encLevel { 532 case protocol.EncryptionInitial: 533 f.Frame = p.retransmissionQueue.GetInitialFrame(maxPacketSize, v) 534 f.Handler = p.retransmissionQueue.InitialAckHandler() 535 case protocol.EncryptionHandshake: 536 f.Frame = p.retransmissionQueue.GetHandshakeFrame(maxPacketSize, v) 537 f.Handler = p.retransmissionQueue.HandshakeAckHandler() 538 } 539 if f.Frame == nil { 540 break 541 } 542 pl.frames = append(pl.frames, f) 543 frameLen := f.Frame.Length(v) 544 pl.length += frameLen 545 maxPacketSize -= frameLen 546 } 547 } else if s.HasData() { 548 cf := s.PopCryptoFrame(maxPacketSize) 549 pl.frames = []ackhandler.Frame{{Frame: cf, Handler: handler}} 550 pl.length += cf.Length(v) 551 } 552 return hdr, pl 553 } 554 555 func (p *packetPacker) maybeGetAppDataPacketFor0RTT(sealer sealer, maxPacketSize protocol.ByteCount, v protocol.Version) (*wire.ExtendedHeader, payload) { 556 if p.perspective != protocol.PerspectiveClient { 557 return nil, payload{} 558 } 559 560 hdr := p.getLongHeader(protocol.Encryption0RTT, v) 561 maxPayloadSize := maxPacketSize - hdr.GetLength(v) - protocol.ByteCount(sealer.Overhead()) 562 return hdr, p.maybeGetAppDataPacket(maxPayloadSize, false, false, v) 563 } 564 565 func (p *packetPacker) maybeGetShortHeaderPacket(sealer handshake.ShortHeaderSealer, hdrLen protocol.ByteCount, maxPacketSize protocol.ByteCount, onlyAck, ackAllowed bool, v protocol.Version) payload { 566 maxPayloadSize := maxPacketSize - hdrLen - protocol.ByteCount(sealer.Overhead()) 567 return p.maybeGetAppDataPacket(maxPayloadSize, onlyAck, ackAllowed, v) 568 } 569 570 func (p *packetPacker) maybeGetAppDataPacket(maxPayloadSize protocol.ByteCount, onlyAck, ackAllowed bool, v protocol.Version) payload { 571 pl := p.composeNextPacket(maxPayloadSize, onlyAck, ackAllowed, v) 572 573 // check if we have anything to send 574 if len(pl.frames) == 0 && len(pl.streamFrames) == 0 { 575 if pl.ack == nil { 576 return payload{} 577 } 578 // the packet only contains an ACK 579 if p.numNonAckElicitingAcks >= protocol.MaxNonAckElicitingAcks { 580 ping := &wire.PingFrame{} 581 pl.frames = append(pl.frames, ackhandler.Frame{Frame: ping}) 582 pl.length += ping.Length(v) 583 p.numNonAckElicitingAcks = 0 584 } else { 585 p.numNonAckElicitingAcks++ 586 } 587 } else { 588 p.numNonAckElicitingAcks = 0 589 } 590 return pl 591 } 592 593 func (p *packetPacker) composeNextPacket(maxFrameSize protocol.ByteCount, onlyAck, ackAllowed bool, v protocol.Version) payload { 594 if onlyAck { 595 if ack := p.acks.GetAckFrame(protocol.Encryption1RTT, true); ack != nil { 596 return payload{ack: ack, length: ack.Length(v)} 597 } 598 return payload{} 599 } 600 601 hasData := p.framer.HasData() 602 hasRetransmission := p.retransmissionQueue.HasAppData() 603 604 var hasAck bool 605 var pl payload 606 if ackAllowed { 607 if ack := p.acks.GetAckFrame(protocol.Encryption1RTT, !hasRetransmission && !hasData); ack != nil { 608 pl.ack = ack 609 pl.length += ack.Length(v) 610 hasAck = true 611 } 612 } 613 614 if p.datagramQueue != nil { 615 if f := p.datagramQueue.Peek(); f != nil { 616 size := f.Length(v) 617 if size <= maxFrameSize-pl.length { // DATAGRAM frame fits 618 pl.frames = append(pl.frames, ackhandler.Frame{Frame: f}) 619 pl.length += size 620 p.datagramQueue.Pop() 621 p.peekTimes = 0 622 } else if !hasAck { 623 // The DATAGRAM frame doesn't fit, and the packet doesn't contain an ACK. 624 // Discard this frame. There's no point in retrying this in the next packet, 625 // as it's unlikely that the available packet size will increase. 626 p.datagramQueue.Pop() 627 p.peekTimes = 0 628 } 629 // If the DATAGRAM frame was too large and the packet contained an ACK, we'll try to send it out later. 630 p.peekTimes++ 631 if p.peekTimes > DatagramFrameMaxPeekTimes { 632 if p.datagramQueue.logger != nil && p.datagramQueue.logger.Debug() { 633 p.datagramQueue.logger.Debugf("Discarded DATAGRAM frame (%d bytes payload)", size) 634 } 635 p.datagramQueue.Pop() 636 p.peekTimes = 0 637 } 638 } 639 } 640 641 if hasAck && !hasData && !hasRetransmission { 642 return pl 643 } 644 645 if hasRetransmission { 646 for { 647 remainingLen := maxFrameSize - pl.length 648 if remainingLen < protocol.MinStreamFrameSize { 649 break 650 } 651 f := p.retransmissionQueue.GetAppDataFrame(remainingLen, v) 652 if f == nil { 653 break 654 } 655 pl.frames = append(pl.frames, ackhandler.Frame{Frame: f, Handler: p.retransmissionQueue.AppDataAckHandler()}) 656 pl.length += f.Length(v) 657 } 658 } 659 660 if hasData { 661 var lengthAdded protocol.ByteCount 662 startLen := len(pl.frames) 663 pl.frames, lengthAdded = p.framer.AppendControlFrames(pl.frames, maxFrameSize-pl.length, v) 664 pl.length += lengthAdded 665 // add handlers for the control frames that were added 666 for i := startLen; i < len(pl.frames); i++ { 667 switch pl.frames[i].Frame.(type) { 668 case *wire.PathChallengeFrame, *wire.PathResponseFrame: 669 // Path probing is currently not supported, therefore we don't need to set the OnAcked callback yet. 670 // PATH_CHALLENGE and PATH_RESPONSE are never retransmitted. 671 default: 672 pl.frames[i].Handler = p.retransmissionQueue.AppDataAckHandler() 673 } 674 } 675 676 pl.streamFrames, lengthAdded = p.framer.AppendStreamFrames(pl.streamFrames, maxFrameSize-pl.length, v) 677 pl.length += lengthAdded 678 } 679 return pl 680 } 681 682 func (p *packetPacker) MaybePackProbePacket(encLevel protocol.EncryptionLevel, maxPacketSize protocol.ByteCount, v protocol.Version) (*coalescedPacket, error) { 683 if encLevel == protocol.Encryption1RTT { 684 s, err := p.cryptoSetup.Get1RTTSealer() 685 if err != nil { 686 return nil, err 687 } 688 kp := s.KeyPhase() 689 connID := p.getDestConnID() 690 pn, pnLen := p.pnManager.PeekPacketNumber(protocol.Encryption1RTT) 691 hdrLen := wire.ShortHeaderLen(connID, pnLen) 692 pl := p.maybeGetAppDataPacket(maxPacketSize-protocol.ByteCount(s.Overhead())-hdrLen, false, true, v) 693 if pl.length == 0 { 694 return nil, nil 695 } 696 buffer := getPacketBuffer() 697 packet := &coalescedPacket{buffer: buffer} 698 shp, err := p.appendShortHeaderPacket(buffer, connID, pn, pnLen, kp, pl, 0, maxPacketSize, s, false, v) 699 if err != nil { 700 buffer.Release() 701 return nil, err 702 } 703 packet.shortHdrPacket = &shp 704 return packet, nil 705 } 706 707 var hdr *wire.ExtendedHeader 708 var pl payload 709 var sealer handshake.LongHeaderSealer 710 //nolint:exhaustive // Probe packets are never sent for 0-RTT. 711 switch encLevel { 712 case protocol.EncryptionInitial: 713 var err error 714 sealer, err = p.cryptoSetup.GetInitialSealer() 715 if err != nil { 716 return nil, err 717 } 718 hdr, pl = p.maybeGetCryptoPacket(maxPacketSize-protocol.ByteCount(sealer.Overhead()), protocol.EncryptionInitial, false, true, v) 719 case protocol.EncryptionHandshake: 720 var err error 721 sealer, err = p.cryptoSetup.GetHandshakeSealer() 722 if err != nil { 723 return nil, err 724 } 725 hdr, pl = p.maybeGetCryptoPacket(maxPacketSize-protocol.ByteCount(sealer.Overhead()), protocol.EncryptionHandshake, false, true, v) 726 default: 727 panic("unknown encryption level") 728 } 729 730 if pl.length == 0 { 731 return nil, nil 732 } 733 buffer := getPacketBuffer() 734 packet := &coalescedPacket{buffer: buffer} 735 size := p.longHeaderPacketLength(hdr, pl, v) + protocol.ByteCount(sealer.Overhead()) 736 var padding protocol.ByteCount 737 if encLevel == protocol.EncryptionInitial { 738 padding = p.initialPaddingLen(pl.frames, size, maxPacketSize) 739 } 740 741 longHdrPacket, err := p.appendLongHeaderPacket(buffer, hdr, pl, padding, encLevel, sealer, v) 742 if err != nil { 743 buffer.Release() 744 return nil, err 745 } 746 packet.longHdrPackets = []*longHeaderPacket{longHdrPacket} 747 return packet, nil 748 } 749 750 func (p *packetPacker) PackMTUProbePacket(ping ackhandler.Frame, size protocol.ByteCount, v protocol.Version) (shortHeaderPacket, *packetBuffer, error) { 751 pl := payload{ 752 frames: []ackhandler.Frame{ping}, 753 length: ping.Frame.Length(v), 754 } 755 buffer := getPacketBuffer() 756 s, err := p.cryptoSetup.Get1RTTSealer() 757 if err != nil { 758 return shortHeaderPacket{}, nil, err 759 } 760 connID := p.getDestConnID() 761 pn, pnLen := p.pnManager.PeekPacketNumber(protocol.Encryption1RTT) 762 padding := size - p.shortHeaderPacketLength(connID, pnLen, pl) - protocol.ByteCount(s.Overhead()) 763 kp := s.KeyPhase() 764 packet, err := p.appendShortHeaderPacket(buffer, connID, pn, pnLen, kp, pl, padding, size, s, true, v) 765 if err != nil { 766 buffer.Release() 767 } 768 return packet, buffer, err 769 } 770 771 func (p *packetPacker) getLongHeader(encLevel protocol.EncryptionLevel, v protocol.Version) *wire.ExtendedHeader { 772 pn, pnLen := p.pnManager.PeekPacketNumber(encLevel) 773 hdr := &wire.ExtendedHeader{ 774 PacketNumber: pn, 775 PacketNumberLen: pnLen, 776 } 777 hdr.Version = v 778 hdr.SrcConnectionID = p.srcConnID 779 hdr.DestConnectionID = p.getDestConnID() 780 781 //nolint:exhaustive // 1-RTT packets are not long header packets. 782 switch encLevel { 783 case protocol.EncryptionInitial: 784 hdr.Type = protocol.PacketTypeInitial 785 hdr.Token = p.token 786 case protocol.EncryptionHandshake: 787 hdr.Type = protocol.PacketTypeHandshake 788 case protocol.Encryption0RTT: 789 hdr.Type = protocol.PacketType0RTT 790 } 791 return hdr 792 } 793 794 func (p *packetPacker) appendLongHeaderPacket(buffer *packetBuffer, header *wire.ExtendedHeader, pl payload, padding protocol.ByteCount, encLevel protocol.EncryptionLevel, sealer sealer, v protocol.Version) (*longHeaderPacket, error) { 795 var paddingLen protocol.ByteCount 796 pnLen := protocol.ByteCount(header.PacketNumberLen) 797 if pl.length < 4-pnLen { 798 paddingLen = 4 - pnLen - pl.length 799 } 800 paddingLen += padding 801 header.Length = pnLen + protocol.ByteCount(sealer.Overhead()) + pl.length + paddingLen 802 803 startLen := len(buffer.Data) 804 raw := buffer.Data[startLen:] 805 raw, err := header.Append(raw, v) 806 if err != nil { 807 return nil, err 808 } 809 payloadOffset := protocol.ByteCount(len(raw)) 810 811 raw, err = p.appendPacketPayload(raw, pl, paddingLen, v) 812 if err != nil { 813 return nil, err 814 } 815 raw = p.encryptPacket(raw, sealer, header.PacketNumber, payloadOffset, pnLen) 816 buffer.Data = buffer.Data[:len(buffer.Data)+len(raw)] 817 818 if pn := p.pnManager.PopPacketNumber(encLevel); pn != header.PacketNumber { 819 return nil, fmt.Errorf("packetPacker BUG: Peeked and Popped packet numbers do not match: expected %d, got %d", pn, header.PacketNumber) 820 } 821 return &longHeaderPacket{ 822 header: header, 823 ack: pl.ack, 824 frames: pl.frames, 825 streamFrames: pl.streamFrames, 826 length: protocol.ByteCount(len(raw)), 827 }, nil 828 } 829 830 func (p *packetPacker) appendShortHeaderPacket( 831 buffer *packetBuffer, 832 connID protocol.ConnectionID, 833 pn protocol.PacketNumber, 834 pnLen protocol.PacketNumberLen, 835 kp protocol.KeyPhaseBit, 836 pl payload, 837 padding, maxPacketSize protocol.ByteCount, 838 sealer sealer, 839 isMTUProbePacket bool, 840 v protocol.Version, 841 ) (shortHeaderPacket, error) { 842 var paddingLen protocol.ByteCount 843 if pl.length < 4-protocol.ByteCount(pnLen) { 844 paddingLen = 4 - protocol.ByteCount(pnLen) - pl.length 845 } 846 paddingLen += padding 847 848 startLen := len(buffer.Data) 849 raw := buffer.Data[startLen:] 850 raw, err := wire.AppendShortHeader(raw, connID, pn, pnLen, kp) 851 if err != nil { 852 return shortHeaderPacket{}, err 853 } 854 payloadOffset := protocol.ByteCount(len(raw)) 855 856 raw, err = p.appendPacketPayload(raw, pl, paddingLen, v) 857 if err != nil { 858 return shortHeaderPacket{}, err 859 } 860 if !isMTUProbePacket { 861 if size := protocol.ByteCount(len(raw) + sealer.Overhead()); size > maxPacketSize { 862 return shortHeaderPacket{}, fmt.Errorf("PacketPacker BUG: packet too large (%d bytes, allowed %d bytes)", size, maxPacketSize) 863 } 864 } 865 raw = p.encryptPacket(raw, sealer, pn, payloadOffset, protocol.ByteCount(pnLen)) 866 buffer.Data = buffer.Data[:len(buffer.Data)+len(raw)] 867 868 if newPN := p.pnManager.PopPacketNumber(protocol.Encryption1RTT); newPN != pn { 869 return shortHeaderPacket{}, fmt.Errorf("packetPacker BUG: Peeked and Popped packet numbers do not match: expected %d, got %d", pn, newPN) 870 } 871 return shortHeaderPacket{ 872 PacketNumber: pn, 873 PacketNumberLen: pnLen, 874 KeyPhase: kp, 875 StreamFrames: pl.streamFrames, 876 Frames: pl.frames, 877 Ack: pl.ack, 878 Length: protocol.ByteCount(len(raw)), 879 DestConnID: connID, 880 IsPathMTUProbePacket: isMTUProbePacket, 881 }, nil 882 } 883 884 // appendPacketPayload serializes the payload of a packet into the raw byte slice. 885 // It modifies the order of payload.frames. 886 func (p *packetPacker) appendPacketPayload(raw []byte, pl payload, paddingLen protocol.ByteCount, v protocol.Version) ([]byte, error) { 887 payloadOffset := len(raw) 888 if pl.ack != nil { 889 var err error 890 raw, err = pl.ack.Append(raw, v) 891 if err != nil { 892 return nil, err 893 } 894 } 895 if paddingLen > 0 { 896 raw = append(raw, make([]byte, paddingLen)...) 897 } 898 // Randomize the order of the control frames. 899 // This makes sure that the receiver doesn't rely on the order in which frames are packed. 900 if len(pl.frames) > 1 { 901 p.rand.Shuffle(len(pl.frames), func(i, j int) { pl.frames[i], pl.frames[j] = pl.frames[j], pl.frames[i] }) 902 } 903 for _, f := range pl.frames { 904 var err error 905 raw, err = f.Frame.Append(raw, v) 906 if err != nil { 907 return nil, err 908 } 909 } 910 for _, f := range pl.streamFrames { 911 var err error 912 raw, err = f.Frame.Append(raw, v) 913 if err != nil { 914 return nil, err 915 } 916 } 917 918 if payloadSize := protocol.ByteCount(len(raw)-payloadOffset) - paddingLen; payloadSize != pl.length { 919 return nil, fmt.Errorf("PacketPacker BUG: payload size inconsistent (expected %d, got %d bytes)", pl.length, payloadSize) 920 } 921 return raw, nil 922 } 923 924 func (p *packetPacker) encryptPacket(raw []byte, sealer sealer, pn protocol.PacketNumber, payloadOffset, pnLen protocol.ByteCount) []byte { 925 _ = sealer.Seal(raw[payloadOffset:payloadOffset], raw[payloadOffset:], pn, raw[:payloadOffset]) 926 raw = raw[:len(raw)+sealer.Overhead()] 927 // apply header protection 928 pnOffset := payloadOffset - pnLen 929 sealer.EncryptHeader(raw[pnOffset+4:pnOffset+4+16], &raw[0], raw[pnOffset:payloadOffset]) 930 return raw 931 } 932 933 func (p *packetPacker) SetToken(token []byte) { 934 p.token = token 935 }