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