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