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  }