golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/quic/conn_send.go (about) 1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build go1.21 6 7 package quic 8 9 import ( 10 "crypto/tls" 11 "errors" 12 "time" 13 ) 14 15 // maybeSend sends datagrams, if possible. 16 // 17 // If sending is blocked by pacing, it returns the next time 18 // a datagram may be sent. 19 // 20 // If sending is blocked indefinitely, it returns the zero Time. 21 func (c *Conn) maybeSend(now time.Time) (next time.Time) { 22 // Assumption: The congestion window is not underutilized. 23 // If congestion control, pacing, and anti-amplification all permit sending, 24 // but we have no packet to send, then we will declare the window underutilized. 25 underutilized := false 26 defer func() { 27 c.loss.cc.setUnderutilized(c.log, underutilized) 28 }() 29 30 // Send one datagram on each iteration of this loop, 31 // until we hit a limit or run out of data to send. 32 // 33 // For each number space where we have write keys, 34 // attempt to construct a packet in that space. 35 // If the packet contains no frames (we have no data in need of sending), 36 // abandon the packet. 37 // 38 // Speculatively constructing packets means we don't need 39 // separate code paths for "do we have data to send?" and 40 // "send the data" that need to be kept in sync. 41 for { 42 limit, next := c.loss.sendLimit(now) 43 if limit == ccBlocked { 44 // If anti-amplification blocks sending, then no packet can be sent. 45 return next 46 } 47 if !c.sendOK(now) { 48 return time.Time{} 49 } 50 // We may still send ACKs, even if congestion control or pacing limit sending. 51 52 // Prepare to write a datagram of at most maxSendSize bytes. 53 c.w.reset(c.loss.maxSendSize()) 54 55 dstConnID, ok := c.connIDState.dstConnID() 56 if !ok { 57 // It is currently not possible for us to end up without a connection ID, 58 // but handle the case anyway. 59 return time.Time{} 60 } 61 62 // Initial packet. 63 pad := false 64 var sentInitial *sentPacket 65 if c.keysInitial.canWrite() { 66 pnumMaxAcked := c.loss.spaces[initialSpace].maxAcked 67 pnum := c.loss.nextNumber(initialSpace) 68 p := longPacket{ 69 ptype: packetTypeInitial, 70 version: quicVersion1, 71 num: pnum, 72 dstConnID: dstConnID, 73 srcConnID: c.connIDState.srcConnID(), 74 extra: c.retryToken, 75 } 76 c.w.startProtectedLongHeaderPacket(pnumMaxAcked, p) 77 c.appendFrames(now, initialSpace, pnum, limit) 78 if logPackets { 79 logSentPacket(c, packetTypeInitial, pnum, p.srcConnID, p.dstConnID, c.w.payload()) 80 } 81 if c.logEnabled(QLogLevelPacket) && len(c.w.payload()) > 0 { 82 c.logPacketSent(packetTypeInitial, pnum, p.srcConnID, p.dstConnID, c.w.packetLen(), c.w.payload()) 83 } 84 sentInitial = c.w.finishProtectedLongHeaderPacket(pnumMaxAcked, c.keysInitial.w, p) 85 if sentInitial != nil { 86 // Client initial packets and ack-eliciting server initial packaets 87 // need to be sent in a datagram padded to at least 1200 bytes. 88 // We can't add the padding yet, however, since we may want to 89 // coalesce additional packets with this one. 90 if c.side == clientSide || sentInitial.ackEliciting { 91 pad = true 92 } 93 } 94 } 95 96 // Handshake packet. 97 if c.keysHandshake.canWrite() { 98 pnumMaxAcked := c.loss.spaces[handshakeSpace].maxAcked 99 pnum := c.loss.nextNumber(handshakeSpace) 100 p := longPacket{ 101 ptype: packetTypeHandshake, 102 version: quicVersion1, 103 num: pnum, 104 dstConnID: dstConnID, 105 srcConnID: c.connIDState.srcConnID(), 106 } 107 c.w.startProtectedLongHeaderPacket(pnumMaxAcked, p) 108 c.appendFrames(now, handshakeSpace, pnum, limit) 109 if logPackets { 110 logSentPacket(c, packetTypeHandshake, pnum, p.srcConnID, p.dstConnID, c.w.payload()) 111 } 112 if c.logEnabled(QLogLevelPacket) && len(c.w.payload()) > 0 { 113 c.logPacketSent(packetTypeHandshake, pnum, p.srcConnID, p.dstConnID, c.w.packetLen(), c.w.payload()) 114 } 115 if sent := c.w.finishProtectedLongHeaderPacket(pnumMaxAcked, c.keysHandshake.w, p); sent != nil { 116 c.packetSent(now, handshakeSpace, sent) 117 if c.side == clientSide { 118 // "[...] a client MUST discard Initial keys when it first 119 // sends a Handshake packet [...]" 120 // https://www.rfc-editor.org/rfc/rfc9001.html#section-4.9.1-2 121 c.discardKeys(now, initialSpace) 122 } 123 } 124 } 125 126 // 1-RTT packet. 127 if c.keysAppData.canWrite() { 128 pnumMaxAcked := c.loss.spaces[appDataSpace].maxAcked 129 pnum := c.loss.nextNumber(appDataSpace) 130 c.w.start1RTTPacket(pnum, pnumMaxAcked, dstConnID) 131 c.appendFrames(now, appDataSpace, pnum, limit) 132 if pad && len(c.w.payload()) > 0 { 133 // 1-RTT packets have no length field and extend to the end 134 // of the datagram, so if we're sending a datagram that needs 135 // padding we need to add it inside the 1-RTT packet. 136 c.w.appendPaddingTo(paddedInitialDatagramSize) 137 pad = false 138 } 139 if logPackets { 140 logSentPacket(c, packetType1RTT, pnum, nil, dstConnID, c.w.payload()) 141 } 142 if c.logEnabled(QLogLevelPacket) && len(c.w.payload()) > 0 { 143 c.logPacketSent(packetType1RTT, pnum, nil, dstConnID, c.w.packetLen(), c.w.payload()) 144 } 145 if sent := c.w.finish1RTTPacket(pnum, pnumMaxAcked, dstConnID, &c.keysAppData); sent != nil { 146 c.packetSent(now, appDataSpace, sent) 147 } 148 } 149 150 buf := c.w.datagram() 151 if len(buf) == 0 { 152 if limit == ccOK { 153 // We have nothing to send, and congestion control does not 154 // block sending. The congestion window is underutilized. 155 underutilized = true 156 } 157 return next 158 } 159 160 if sentInitial != nil { 161 if pad { 162 // Pad out the datagram with zeros, coalescing the Initial 163 // packet with invalid packets that will be ignored by the peer. 164 // https://www.rfc-editor.org/rfc/rfc9000.html#section-14.1-1 165 for len(buf) < paddedInitialDatagramSize { 166 buf = append(buf, 0) 167 // Technically this padding isn't in any packet, but 168 // account it to the Initial packet in this datagram 169 // for purposes of flow control and loss recovery. 170 sentInitial.size++ 171 sentInitial.inFlight = true 172 } 173 } 174 // If we're a client and this Initial packet is coalesced 175 // with a Handshake packet, then we've discarded Initial keys 176 // since constructing the packet and shouldn't record it as in-flight. 177 if c.keysInitial.canWrite() { 178 c.packetSent(now, initialSpace, sentInitial) 179 } 180 } 181 182 c.endpoint.sendDatagram(datagram{ 183 b: buf, 184 peerAddr: c.peerAddr, 185 }) 186 } 187 } 188 189 func (c *Conn) packetSent(now time.Time, space numberSpace, sent *sentPacket) { 190 c.idleHandlePacketSent(now, sent) 191 c.loss.packetSent(now, c.log, space, sent) 192 } 193 194 func (c *Conn) appendFrames(now time.Time, space numberSpace, pnum packetNumber, limit ccLimit) { 195 if c.lifetime.localErr != nil { 196 c.appendConnectionCloseFrame(now, space, c.lifetime.localErr) 197 return 198 } 199 200 shouldSendAck := c.acks[space].shouldSendAck(now) 201 if limit != ccOK { 202 // ACKs are not limited by congestion control. 203 if shouldSendAck && c.appendAckFrame(now, space) { 204 c.acks[space].sentAck() 205 } 206 return 207 } 208 // We want to send an ACK frame if the ack controller wants to send a frame now, 209 // OR if we are sending a packet anyway and have ack-eliciting packets which we 210 // have not yet acked. 211 // 212 // We speculatively add ACK frames here, to put them at the front of the packet 213 // to avoid truncation. 214 // 215 // After adding all frames, if we don't need to send an ACK frame and have not 216 // added any other frames, we abandon the packet. 217 if c.appendAckFrame(now, space) { 218 defer func() { 219 // All frames other than ACK and PADDING are ack-eliciting, 220 // so if the packet is ack-eliciting we've added additional 221 // frames to it. 222 if !shouldSendAck && !c.w.sent.ackEliciting { 223 // There's nothing in this packet but ACK frames, and 224 // we don't want to send an ACK-only packet at this time. 225 // Abandoning the packet means we wrote an ACK frame for 226 // nothing, but constructing the frame is cheap. 227 c.w.abandonPacket() 228 return 229 } 230 // Either we are willing to send an ACK-only packet, 231 // or we've added additional frames. 232 c.acks[space].sentAck() 233 if !c.w.sent.ackEliciting && c.shouldMakePacketAckEliciting() { 234 c.w.appendPingFrame() 235 } 236 }() 237 } 238 if limit != ccOK { 239 return 240 } 241 pto := c.loss.ptoExpired 242 243 // TODO: Add all the other frames we can send. 244 245 // CRYPTO 246 c.crypto[space].dataToSend(pto, func(off, size int64) int64 { 247 b, _ := c.w.appendCryptoFrame(off, int(size)) 248 c.crypto[space].sendData(off, b) 249 return int64(len(b)) 250 }) 251 252 // Test-only PING frames. 253 if space == c.testSendPingSpace && c.testSendPing.shouldSendPTO(pto) { 254 if !c.w.appendPingFrame() { 255 return 256 } 257 c.testSendPing.setSent(pnum) 258 } 259 260 if space == appDataSpace { 261 // HANDSHAKE_DONE 262 if c.handshakeConfirmed.shouldSendPTO(pto) { 263 if !c.w.appendHandshakeDoneFrame() { 264 return 265 } 266 c.handshakeConfirmed.setSent(pnum) 267 } 268 269 // NEW_CONNECTION_ID, RETIRE_CONNECTION_ID 270 if !c.connIDState.appendFrames(c, pnum, pto) { 271 return 272 } 273 274 // PATH_RESPONSE 275 if pad, ok := c.appendPathFrames(); !ok { 276 return 277 } else if pad { 278 defer c.w.appendPaddingTo(smallestMaxDatagramSize) 279 } 280 281 // All stream-related frames. This should come last in the packet, 282 // so large amounts of STREAM data don't crowd out other frames 283 // we may need to send. 284 if !c.appendStreamFrames(&c.w, pnum, pto) { 285 return 286 } 287 288 if !c.appendKeepAlive(now) { 289 return 290 } 291 } 292 293 // If this is a PTO probe and we haven't added an ack-eliciting frame yet, 294 // add a PING to make this an ack-eliciting probe. 295 // 296 // Technically, there are separate PTO timers for each number space. 297 // When a PTO timer expires, we MUST send an ack-eliciting packet in the 298 // timer's space. We SHOULD send ack-eliciting packets in every other space 299 // with in-flight data. (RFC 9002, section 6.2.4) 300 // 301 // What we actually do is send a single datagram containing an ack-eliciting packet 302 // for every space for which we have keys. 303 // 304 // We fill the PTO probe packets with new or unacknowledged data. For example, 305 // a PTO probe sent for the Initial space will generally retransmit previously 306 // sent but unacknowledged CRYPTO data. 307 // 308 // When sending a PTO probe datagram containing multiple packets, it is 309 // possible that an earlier packet will fill up the datagram, leaving no 310 // space for the remaining probe packet(s). This is not a problem in practice. 311 // 312 // A client discards Initial keys when it first sends a Handshake packet 313 // (RFC 9001 Section 4.9.1). Handshake keys are discarded when the handshake 314 // is confirmed (RFC 9001 Section 4.9.2). The PTO timer is not set for the 315 // Application Data packet number space until the handshake is confirmed 316 // (RFC 9002 Section 6.2.1). Therefore, the only times a PTO probe can fire 317 // while data for multiple spaces is in flight are: 318 // 319 // - a server's Initial or Handshake timers can fire while Initial and Handshake 320 // data is in flight; and 321 // 322 // - a client's Handshake timer can fire while Handshake and Application Data 323 // data is in flight. 324 // 325 // It is theoretically possible for a server's Initial CRYPTO data to overflow 326 // the maximum datagram size, but unlikely in practice; this space contains 327 // only the ServerHello TLS message, which is small. It's also unlikely that 328 // the Handshake PTO probe will fire while Initial data is in flight (this 329 // requires not just that the Initial CRYPTO data completely fill a datagram, 330 // but a quite specific arrangement of lost and retransmitted packets.) 331 // We don't bother worrying about this case here, since the worst case is 332 // that we send a PTO probe for the in-flight Initial data and drop the 333 // Handshake probe. 334 // 335 // If a client's Handshake PTO timer fires while Application Data data is in 336 // flight, it is possible that the resent Handshake CRYPTO data will crowd 337 // out the probe for the Application Data space. However, since this probe is 338 // optional (recall that the Application Data PTO timer is never set until 339 // after Handshake keys have been discarded), dropping it is acceptable. 340 if pto && !c.w.sent.ackEliciting { 341 c.w.appendPingFrame() 342 } 343 } 344 345 // shouldMakePacketAckEliciting is called when sending a packet containing nothing but an ACK frame. 346 // It reports whether we should add a PING frame to the packet to make it ack-eliciting. 347 func (c *Conn) shouldMakePacketAckEliciting() bool { 348 if c.keysAppData.needAckEliciting() { 349 // The peer has initiated a key update. 350 // We haven't sent them any packets yet in the new phase. 351 // Make this an ack-eliciting packet. 352 // Their ack of this packet will complete the key update. 353 return true 354 } 355 if c.loss.consecutiveNonAckElicitingPackets >= 19 { 356 // We've sent a run of non-ack-eliciting packets. 357 // Add in an ack-eliciting one every once in a while so the peer 358 // lets us know which ones have arrived. 359 // 360 // Google QUICHE injects a PING after sending 19 packets. We do the same. 361 // 362 // https://www.rfc-editor.org/rfc/rfc9000#section-13.2.4-2 363 return true 364 } 365 // TODO: Consider making every packet sent when in PTO ack-eliciting to speed up recovery. 366 return false 367 } 368 369 func (c *Conn) appendAckFrame(now time.Time, space numberSpace) bool { 370 seen, delay := c.acks[space].acksToSend(now) 371 if len(seen) == 0 { 372 return false 373 } 374 d := unscaledAckDelayFromDuration(delay, ackDelayExponent) 375 return c.w.appendAckFrame(seen, d) 376 } 377 378 func (c *Conn) appendConnectionCloseFrame(now time.Time, space numberSpace, err error) { 379 c.sentConnectionClose(now) 380 switch e := err.(type) { 381 case localTransportError: 382 c.w.appendConnectionCloseTransportFrame(e.code, 0, e.reason) 383 case *ApplicationError: 384 if space != appDataSpace { 385 // "CONNECTION_CLOSE frames signaling application errors (type 0x1d) 386 // MUST only appear in the application data packet number space." 387 // https://www.rfc-editor.org/rfc/rfc9000#section-12.5-2.2 388 c.w.appendConnectionCloseTransportFrame(errApplicationError, 0, "") 389 } else { 390 c.w.appendConnectionCloseApplicationFrame(e.Code, e.Reason) 391 } 392 default: 393 // TLS alerts are sent using error codes [0x0100,0x01ff). 394 // https://www.rfc-editor.org/rfc/rfc9000#section-20.1-2.36.1 395 var alert tls.AlertError 396 switch { 397 case errors.As(err, &alert): 398 // tls.AlertError is a uint8, so this can't exceed 0x01ff. 399 code := errTLSBase + transportError(alert) 400 c.w.appendConnectionCloseTransportFrame(code, 0, "") 401 default: 402 c.w.appendConnectionCloseTransportFrame(errInternal, 0, "") 403 } 404 } 405 }