Source file src/vendor/golang.org/x/net/quic/packet_writer.go

     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  package quic
     6  
     7  import (
     8  	"encoding/binary"
     9  
    10  	"golang.org/x/net/internal/quic/quicwire"
    11  )
    12  
    13  // A packetWriter constructs QUIC datagrams.
    14  //
    15  // A datagram consists of one or more packets.
    16  // A packet consists of a header followed by one or more frames.
    17  //
    18  // Packets are written in three steps:
    19  // - startProtectedLongHeaderPacket or start1RTT packet prepare the packet;
    20  // - append*Frame appends frames to the payload; and
    21  // - finishProtectedLongHeaderPacket or finish1RTT finalize the packet.
    22  //
    23  // The start functions are efficient, so we can start speculatively
    24  // writing a packet before we know whether we have any frames to
    25  // put in it. The finish functions will abandon the packet if the
    26  // payload contains no data.
    27  type packetWriter struct {
    28  	dgramLim int // max datagram size
    29  	pktLim   int // max packet size
    30  	pktOff   int // offset of the start of the current packet
    31  	payOff   int // offset of the payload of the current packet
    32  	b        []byte
    33  	sent     *sentPacket
    34  }
    35  
    36  // reset prepares to write a datagram of at most lim bytes.
    37  func (w *packetWriter) reset(lim int) {
    38  	if cap(w.b) < lim {
    39  		w.b = make([]byte, 0, lim)
    40  	}
    41  	w.dgramLim = lim
    42  	w.b = w.b[:0]
    43  }
    44  
    45  // datagram returns the current datagram.
    46  func (w *packetWriter) datagram() []byte {
    47  	return w.b
    48  }
    49  
    50  // packetLen returns the size of the current packet.
    51  func (w *packetWriter) packetLen() int {
    52  	return len(w.b[w.pktOff:]) + aeadOverhead
    53  }
    54  
    55  // payload returns the payload of the current packet.
    56  func (w *packetWriter) payload() []byte {
    57  	return w.b[w.payOff:]
    58  }
    59  
    60  func (w *packetWriter) abandonPacket() {
    61  	w.b = w.b[:w.payOff]
    62  	w.sent.reset()
    63  }
    64  
    65  // startProtectedLongHeaderPacket starts writing an Initial, 0-RTT, or Handshake packet.
    66  func (w *packetWriter) startProtectedLongHeaderPacket(pnumMaxAcked packetNumber, p longPacket) {
    67  	if w.sent == nil {
    68  		w.sent = newSentPacket()
    69  	}
    70  	w.pktOff = len(w.b)
    71  	hdrSize := 1 // packet type
    72  	hdrSize += 4 // version
    73  	hdrSize += 1 + len(p.dstConnID)
    74  	hdrSize += 1 + len(p.srcConnID)
    75  	switch p.ptype {
    76  	case packetTypeInitial:
    77  		hdrSize += quicwire.SizeVarint(uint64(len(p.extra))) + len(p.extra)
    78  	}
    79  	hdrSize += 2 // length, hardcoded to a 2-byte varint
    80  	pnumOff := len(w.b) + hdrSize
    81  	hdrSize += packetNumberLength(p.num, pnumMaxAcked)
    82  	payOff := len(w.b) + hdrSize
    83  	// Check if we have enough space to hold the packet, including the header,
    84  	// header protection sample (RFC 9001, section 5.4.2), and encryption overhead.
    85  	if pnumOff+4+headerProtectionSampleSize+aeadOverhead >= w.dgramLim {
    86  		// Set the limit on the packet size to be the current write buffer length,
    87  		// ensuring that any writes to the payload fail.
    88  		w.payOff = len(w.b)
    89  		w.pktLim = len(w.b)
    90  		return
    91  	}
    92  	w.payOff = payOff
    93  	w.pktLim = w.dgramLim - aeadOverhead
    94  	// We hardcode the payload length field to be 2 bytes, which limits the payload
    95  	// (including the packet number) to 16383 bytes (the largest 2-byte QUIC varint).
    96  	//
    97  	// Most networks don't support datagrams over 1472 bytes, and even Ethernet
    98  	// jumbo frames are generally only about 9000 bytes.
    99  	if lim := pnumOff + 16383 - aeadOverhead; lim < w.pktLim {
   100  		w.pktLim = lim
   101  	}
   102  	w.b = w.b[:payOff]
   103  }
   104  
   105  // finishProtectedLongHeaderPacket finishes writing an Initial, 0-RTT, or Handshake packet,
   106  // canceling the packet if it contains no payload.
   107  // It returns a sentPacket describing the packet, or nil if no packet was written.
   108  func (w *packetWriter) finishProtectedLongHeaderPacket(pnumMaxAcked packetNumber, k fixedKeys, p longPacket) *sentPacket {
   109  	if len(w.b) == w.payOff {
   110  		// The payload is empty, so just abandon the packet.
   111  		w.b = w.b[:w.pktOff]
   112  		return nil
   113  	}
   114  	pnumLen := packetNumberLength(p.num, pnumMaxAcked)
   115  	plen := w.padPacketLength(pnumLen)
   116  	hdr := w.b[:w.pktOff]
   117  	var typeBits byte
   118  	switch p.ptype {
   119  	case packetTypeInitial:
   120  		typeBits = longPacketTypeInitial
   121  	case packetType0RTT:
   122  		typeBits = longPacketType0RTT
   123  	case packetTypeHandshake:
   124  		typeBits = longPacketTypeHandshake
   125  	case packetTypeRetry:
   126  		typeBits = longPacketTypeRetry
   127  	}
   128  	hdr = append(hdr, headerFormLong|fixedBit|typeBits|byte(pnumLen-1))
   129  	hdr = binary.BigEndian.AppendUint32(hdr, p.version)
   130  	hdr = quicwire.AppendUint8Bytes(hdr, p.dstConnID)
   131  	hdr = quicwire.AppendUint8Bytes(hdr, p.srcConnID)
   132  	switch p.ptype {
   133  	case packetTypeInitial:
   134  		hdr = quicwire.AppendVarintBytes(hdr, p.extra) // token
   135  	}
   136  
   137  	// Packet length, always encoded as a 2-byte varint.
   138  	hdr = append(hdr, 0x40|byte(plen>>8), byte(plen))
   139  
   140  	pnumOff := len(hdr)
   141  	hdr = appendPacketNumber(hdr, p.num, pnumMaxAcked)
   142  
   143  	k.protect(hdr[w.pktOff:], w.b[len(hdr):], pnumOff-w.pktOff, p.num)
   144  	return w.finish(p.ptype, p.num)
   145  }
   146  
   147  // start1RTTPacket starts writing a 1-RTT (short header) packet.
   148  func (w *packetWriter) start1RTTPacket(pnum, pnumMaxAcked packetNumber, dstConnID []byte) {
   149  	if w.sent == nil {
   150  		w.sent = newSentPacket()
   151  	}
   152  	w.pktOff = len(w.b)
   153  	hdrSize := 1 // packet type
   154  	hdrSize += len(dstConnID)
   155  	// Ensure we have enough space to hold the packet, including the header,
   156  	// header protection sample (RFC 9001, section 5.4.2), and encryption overhead.
   157  	if len(w.b)+hdrSize+4+headerProtectionSampleSize+aeadOverhead >= w.dgramLim {
   158  		w.payOff = len(w.b)
   159  		w.pktLim = len(w.b)
   160  		return
   161  	}
   162  	hdrSize += packetNumberLength(pnum, pnumMaxAcked)
   163  	w.payOff = len(w.b) + hdrSize
   164  	w.pktLim = w.dgramLim - aeadOverhead
   165  	w.b = w.b[:w.payOff]
   166  }
   167  
   168  // finish1RTTPacket finishes writing a 1-RTT packet,
   169  // canceling the packet if it contains no payload.
   170  // It returns a sentPacket describing the packet, or nil if no packet was written.
   171  func (w *packetWriter) finish1RTTPacket(pnum, pnumMaxAcked packetNumber, dstConnID []byte, k *updatingKeyPair) *sentPacket {
   172  	if len(w.b) == w.payOff {
   173  		// The payload is empty, so just abandon the packet.
   174  		w.b = w.b[:w.pktOff]
   175  		return nil
   176  	}
   177  	// TODO: Spin
   178  	pnumLen := packetNumberLength(pnum, pnumMaxAcked)
   179  	hdr := w.b[:w.pktOff]
   180  	hdr = append(hdr, 0x40|byte(pnumLen-1))
   181  	hdr = append(hdr, dstConnID...)
   182  	pnumOff := len(hdr)
   183  	hdr = appendPacketNumber(hdr, pnum, pnumMaxAcked)
   184  	w.padPacketLength(pnumLen)
   185  	k.protect(hdr[w.pktOff:], w.b[len(hdr):], pnumOff-w.pktOff, pnum)
   186  	return w.finish(packetType1RTT, pnum)
   187  }
   188  
   189  // padPacketLength pads out the payload of the current packet to the minimum size,
   190  // and returns the combined length of the packet number and payload (used for the Length
   191  // field of long header packets).
   192  func (w *packetWriter) padPacketLength(pnumLen int) int {
   193  	plen := len(w.b) - w.payOff + pnumLen + aeadOverhead
   194  	// "To ensure that sufficient data is available for sampling, packets are
   195  	// padded so that the combined lengths of the encoded packet number and
   196  	// protected payload is at least 4 bytes longer than the sample required
   197  	// for header protection."
   198  	// https://www.rfc-editor.org/rfc/rfc9001.html#section-5.4.2
   199  	for plen < 4+headerProtectionSampleSize {
   200  		w.b = append(w.b, 0)
   201  		plen++
   202  	}
   203  	return plen
   204  }
   205  
   206  // finish finishes the current packet after protection is applied.
   207  func (w *packetWriter) finish(ptype packetType, pnum packetNumber) *sentPacket {
   208  	w.b = w.b[:len(w.b)+aeadOverhead]
   209  	w.sent.size = len(w.b) - w.pktOff
   210  	w.sent.ptype = ptype
   211  	w.sent.num = pnum
   212  	sent := w.sent
   213  	w.sent = nil
   214  	return sent
   215  }
   216  
   217  // avail reports how many more bytes may be written to the current packet.
   218  func (w *packetWriter) avail() int {
   219  	return w.pktLim - len(w.b)
   220  }
   221  
   222  // appendPaddingTo appends PADDING frames until the total datagram size
   223  // (including AEAD overhead of the current packet) is n.
   224  func (w *packetWriter) appendPaddingTo(n int) {
   225  	n -= aeadOverhead
   226  	lim := w.pktLim
   227  	if n < lim {
   228  		lim = n
   229  	}
   230  	if len(w.b) >= lim {
   231  		return
   232  	}
   233  	for len(w.b) < lim {
   234  		w.b = append(w.b, frameTypePadding)
   235  	}
   236  	// Packets are considered in flight when they contain a PADDING frame.
   237  	// https://www.rfc-editor.org/rfc/rfc9002.html#section-2-3.6.1
   238  	w.sent.inFlight = true
   239  }
   240  
   241  func (w *packetWriter) appendPingFrame() (added bool) {
   242  	if len(w.b) >= w.pktLim {
   243  		return false
   244  	}
   245  	w.b = append(w.b, frameTypePing)
   246  	w.sent.markAckEliciting() // no need to record the frame itself
   247  	return true
   248  }
   249  
   250  // appendAckFrame appends an ACK frame to the payload.
   251  // It includes at least the most recent range in the rangeset
   252  // (the range with the largest packet numbers),
   253  // followed by as many additional ranges as fit within the packet.
   254  //
   255  // We always place ACK frames at the start of packets,
   256  // we limit the number of ack ranges retained, and
   257  // we set a minimum packet payload size.
   258  // As a result, appendAckFrame will rarely if ever drop ranges
   259  // in practice.
   260  //
   261  // In the event that ranges are dropped, the impact is limited
   262  // to the peer potentially failing to receive an acknowledgement
   263  // for an older packet during a period of high packet loss or
   264  // reordering. This may result in unnecessary retransmissions.
   265  func (w *packetWriter) appendAckFrame(seen rangeset[packetNumber], delay unscaledAckDelay, ecn ecnCounts) (added bool) {
   266  	if len(seen) == 0 {
   267  		return false
   268  	}
   269  	var (
   270  		largest    = uint64(seen.max())
   271  		firstRange = uint64(seen[len(seen)-1].size() - 1)
   272  	)
   273  	var ecnLen int
   274  	ackType := byte(frameTypeAck)
   275  	if (ecn != ecnCounts{}) {
   276  		// "Even if an endpoint does not set an ECT field in packets it sends,
   277  		// the endpoint MUST provide feedback about ECN markings it receives, if
   278  		// these are accessible."
   279  		// https://www.rfc-editor.org/rfc/rfc9000.html#section-13.4.1-2
   280  		ecnLen = quicwire.SizeVarint(uint64(ecn.ce)) + quicwire.SizeVarint(uint64(ecn.t0)) + quicwire.SizeVarint(uint64(ecn.t1))
   281  		ackType = frameTypeAckECN
   282  	}
   283  	if w.avail() < 1+quicwire.SizeVarint(largest)+quicwire.SizeVarint(uint64(delay))+1+quicwire.SizeVarint(firstRange)+ecnLen {
   284  		return false
   285  	}
   286  	w.b = append(w.b, ackType)
   287  	w.b = quicwire.AppendVarint(w.b, largest)
   288  	w.b = quicwire.AppendVarint(w.b, uint64(delay))
   289  	// The range count is technically a varint, but we'll reserve a single byte for it
   290  	// and never add more than 62 ranges (the maximum varint that fits in a byte).
   291  	rangeCountOff := len(w.b)
   292  	w.b = append(w.b, 0)
   293  	w.b = quicwire.AppendVarint(w.b, firstRange)
   294  	rangeCount := byte(0)
   295  	for i := len(seen) - 2; i >= 0; i-- {
   296  		gap := uint64(seen[i+1].start - seen[i].end - 1)
   297  		size := uint64(seen[i].size() - 1)
   298  		if w.avail() < quicwire.SizeVarint(gap)+quicwire.SizeVarint(size)+ecnLen || rangeCount > 62 {
   299  			break
   300  		}
   301  		w.b = quicwire.AppendVarint(w.b, gap)
   302  		w.b = quicwire.AppendVarint(w.b, size)
   303  		rangeCount++
   304  	}
   305  	w.b[rangeCountOff] = rangeCount
   306  	if ackType == frameTypeAckECN {
   307  		w.b = quicwire.AppendVarint(w.b, uint64(ecn.t0))
   308  		w.b = quicwire.AppendVarint(w.b, uint64(ecn.t1))
   309  		w.b = quicwire.AppendVarint(w.b, uint64(ecn.ce))
   310  	}
   311  	w.sent.appendNonAckElicitingFrame(ackType)
   312  	w.sent.appendInt(uint64(seen.max()))
   313  	return true
   314  }
   315  
   316  func (w *packetWriter) appendNewTokenFrame(token []byte) (added bool) {
   317  	if w.avail() < 1+quicwire.SizeVarint(uint64(len(token)))+len(token) {
   318  		return false
   319  	}
   320  	w.b = append(w.b, frameTypeNewToken)
   321  	w.b = quicwire.AppendVarintBytes(w.b, token)
   322  	return true
   323  }
   324  
   325  func (w *packetWriter) appendResetStreamFrame(id streamID, code uint64, finalSize int64) (added bool) {
   326  	if w.avail() < 1+quicwire.SizeVarint(uint64(id))+quicwire.SizeVarint(code)+quicwire.SizeVarint(uint64(finalSize)) {
   327  		return false
   328  	}
   329  	w.b = append(w.b, frameTypeResetStream)
   330  	w.b = quicwire.AppendVarint(w.b, uint64(id))
   331  	w.b = quicwire.AppendVarint(w.b, code)
   332  	w.b = quicwire.AppendVarint(w.b, uint64(finalSize))
   333  	w.sent.appendAckElicitingFrame(frameTypeResetStream)
   334  	w.sent.appendInt(uint64(id))
   335  	return true
   336  }
   337  
   338  func (w *packetWriter) appendStopSendingFrame(id streamID, code uint64) (added bool) {
   339  	if w.avail() < 1+quicwire.SizeVarint(uint64(id))+quicwire.SizeVarint(code) {
   340  		return false
   341  	}
   342  	w.b = append(w.b, frameTypeStopSending)
   343  	w.b = quicwire.AppendVarint(w.b, uint64(id))
   344  	w.b = quicwire.AppendVarint(w.b, code)
   345  	w.sent.appendAckElicitingFrame(frameTypeStopSending)
   346  	w.sent.appendInt(uint64(id))
   347  	return true
   348  }
   349  
   350  // appendCryptoFrame appends a CRYPTO frame.
   351  // It returns a []byte into which the data should be written and whether a frame was added.
   352  // The returned []byte may be smaller than size if the packet cannot hold all the data.
   353  func (w *packetWriter) appendCryptoFrame(off int64, size int) (_ []byte, added bool) {
   354  	max := w.avail()
   355  	max -= 1                                 // frame type
   356  	max -= quicwire.SizeVarint(uint64(off))  // offset
   357  	max -= quicwire.SizeVarint(uint64(size)) // maximum length
   358  	if max <= 0 {
   359  		return nil, false
   360  	}
   361  	if max < size {
   362  		size = max
   363  	}
   364  	w.b = append(w.b, frameTypeCrypto)
   365  	w.b = quicwire.AppendVarint(w.b, uint64(off))
   366  	w.b = quicwire.AppendVarint(w.b, uint64(size))
   367  	start := len(w.b)
   368  	w.b = w.b[:start+size]
   369  	w.sent.appendAckElicitingFrame(frameTypeCrypto)
   370  	w.sent.appendOffAndSize(off, size)
   371  	return w.b[start:][:size], true
   372  }
   373  
   374  // appendStreamFrame appends a STREAM frame.
   375  // It returns a []byte into which the data should be written and whether a frame was added.
   376  // The returned []byte may be smaller than size if the packet cannot hold all the data.
   377  func (w *packetWriter) appendStreamFrame(id streamID, off int64, size int, fin bool) (_ []byte, added bool) {
   378  	typ := uint8(frameTypeStreamBase | streamLenBit)
   379  	max := w.avail()
   380  	max -= 1 // frame type
   381  	max -= quicwire.SizeVarint(uint64(id))
   382  	if off != 0 {
   383  		max -= quicwire.SizeVarint(uint64(off))
   384  		typ |= streamOffBit
   385  	}
   386  	max -= quicwire.SizeVarint(uint64(size)) // maximum length
   387  	if max < 0 || (max == 0 && size > 0) {
   388  		return nil, false
   389  	}
   390  	if max < size {
   391  		size = max
   392  	} else if fin {
   393  		typ |= streamFinBit
   394  	}
   395  	w.b = append(w.b, typ)
   396  	w.b = quicwire.AppendVarint(w.b, uint64(id))
   397  	if off != 0 {
   398  		w.b = quicwire.AppendVarint(w.b, uint64(off))
   399  	}
   400  	w.b = quicwire.AppendVarint(w.b, uint64(size))
   401  	start := len(w.b)
   402  	w.b = w.b[:start+size]
   403  	w.sent.appendAckElicitingFrame(typ & (frameTypeStreamBase | streamFinBit))
   404  	w.sent.appendInt(uint64(id))
   405  	w.sent.appendOffAndSize(off, size)
   406  	return w.b[start:][:size], true
   407  }
   408  
   409  func (w *packetWriter) appendMaxDataFrame(max int64) (added bool) {
   410  	if w.avail() < 1+quicwire.SizeVarint(uint64(max)) {
   411  		return false
   412  	}
   413  	w.b = append(w.b, frameTypeMaxData)
   414  	w.b = quicwire.AppendVarint(w.b, uint64(max))
   415  	w.sent.appendAckElicitingFrame(frameTypeMaxData)
   416  	return true
   417  }
   418  
   419  func (w *packetWriter) appendMaxStreamDataFrame(id streamID, max int64) (added bool) {
   420  	if w.avail() < 1+quicwire.SizeVarint(uint64(id))+quicwire.SizeVarint(uint64(max)) {
   421  		return false
   422  	}
   423  	w.b = append(w.b, frameTypeMaxStreamData)
   424  	w.b = quicwire.AppendVarint(w.b, uint64(id))
   425  	w.b = quicwire.AppendVarint(w.b, uint64(max))
   426  	w.sent.appendAckElicitingFrame(frameTypeMaxStreamData)
   427  	w.sent.appendInt(uint64(id))
   428  	return true
   429  }
   430  
   431  func (w *packetWriter) appendMaxStreamsFrame(streamType streamType, max int64) (added bool) {
   432  	if w.avail() < 1+quicwire.SizeVarint(uint64(max)) {
   433  		return false
   434  	}
   435  	var typ byte
   436  	if streamType == bidiStream {
   437  		typ = frameTypeMaxStreamsBidi
   438  	} else {
   439  		typ = frameTypeMaxStreamsUni
   440  	}
   441  	w.b = append(w.b, typ)
   442  	w.b = quicwire.AppendVarint(w.b, uint64(max))
   443  	w.sent.appendAckElicitingFrame(typ)
   444  	return true
   445  }
   446  
   447  func (w *packetWriter) appendDataBlockedFrame(max int64) (added bool) {
   448  	if w.avail() < 1+quicwire.SizeVarint(uint64(max)) {
   449  		return false
   450  	}
   451  	w.b = append(w.b, frameTypeDataBlocked)
   452  	w.b = quicwire.AppendVarint(w.b, uint64(max))
   453  	w.sent.appendAckElicitingFrame(frameTypeDataBlocked)
   454  	return true
   455  }
   456  
   457  func (w *packetWriter) appendStreamDataBlockedFrame(id streamID, max int64) (added bool) {
   458  	if w.avail() < 1+quicwire.SizeVarint(uint64(id))+quicwire.SizeVarint(uint64(max)) {
   459  		return false
   460  	}
   461  	w.b = append(w.b, frameTypeStreamDataBlocked)
   462  	w.b = quicwire.AppendVarint(w.b, uint64(id))
   463  	w.b = quicwire.AppendVarint(w.b, uint64(max))
   464  	w.sent.appendAckElicitingFrame(frameTypeStreamDataBlocked)
   465  	w.sent.appendInt(uint64(id))
   466  	return true
   467  }
   468  
   469  func (w *packetWriter) appendStreamsBlockedFrame(typ streamType, max int64) (added bool) {
   470  	if w.avail() < 1+quicwire.SizeVarint(uint64(max)) {
   471  		return false
   472  	}
   473  	var ftype byte
   474  	if typ == bidiStream {
   475  		ftype = frameTypeStreamsBlockedBidi
   476  	} else {
   477  		ftype = frameTypeStreamsBlockedUni
   478  	}
   479  	w.b = append(w.b, ftype)
   480  	w.b = quicwire.AppendVarint(w.b, uint64(max))
   481  	w.sent.appendAckElicitingFrame(ftype)
   482  	return true
   483  }
   484  
   485  func (w *packetWriter) appendNewConnectionIDFrame(seq, retirePriorTo int64, connID []byte, token [16]byte) (added bool) {
   486  	if w.avail() < 1+quicwire.SizeVarint(uint64(seq))+quicwire.SizeVarint(uint64(retirePriorTo))+1+len(connID)+len(token) {
   487  		return false
   488  	}
   489  	w.b = append(w.b, frameTypeNewConnectionID)
   490  	w.b = quicwire.AppendVarint(w.b, uint64(seq))
   491  	w.b = quicwire.AppendVarint(w.b, uint64(retirePriorTo))
   492  	w.b = quicwire.AppendUint8Bytes(w.b, connID)
   493  	w.b = append(w.b, token[:]...)
   494  	w.sent.appendAckElicitingFrame(frameTypeNewConnectionID)
   495  	w.sent.appendInt(uint64(seq))
   496  	return true
   497  }
   498  
   499  func (w *packetWriter) appendRetireConnectionIDFrame(seq int64) (added bool) {
   500  	if w.avail() < 1+quicwire.SizeVarint(uint64(seq)) {
   501  		return false
   502  	}
   503  	w.b = append(w.b, frameTypeRetireConnectionID)
   504  	w.b = quicwire.AppendVarint(w.b, uint64(seq))
   505  	w.sent.appendAckElicitingFrame(frameTypeRetireConnectionID)
   506  	w.sent.appendInt(uint64(seq))
   507  	return true
   508  }
   509  
   510  func (w *packetWriter) appendPathChallengeFrame(data pathChallengeData) (added bool) {
   511  	if w.avail() < 1+8 {
   512  		return false
   513  	}
   514  	w.b = append(w.b, frameTypePathChallenge)
   515  	w.b = append(w.b, data[:]...)
   516  	w.sent.markAckEliciting() // no need to record the frame itself
   517  	return true
   518  }
   519  
   520  func (w *packetWriter) appendPathResponseFrame(data pathChallengeData) (added bool) {
   521  	if w.avail() < 1+8 {
   522  		return false
   523  	}
   524  	w.b = append(w.b, frameTypePathResponse)
   525  	w.b = append(w.b, data[:]...)
   526  	w.sent.markAckEliciting() // no need to record the frame itself
   527  	return true
   528  }
   529  
   530  // appendConnectionCloseTransportFrame appends a CONNECTION_CLOSE frame
   531  // carrying a transport error code.
   532  func (w *packetWriter) appendConnectionCloseTransportFrame(code transportError, frameType uint64, reason string) (added bool) {
   533  	if w.avail() < 1+quicwire.SizeVarint(uint64(code))+quicwire.SizeVarint(frameType)+quicwire.SizeVarint(uint64(len(reason)))+len(reason) {
   534  		return false
   535  	}
   536  	w.b = append(w.b, frameTypeConnectionCloseTransport)
   537  	w.b = quicwire.AppendVarint(w.b, uint64(code))
   538  	w.b = quicwire.AppendVarint(w.b, frameType)
   539  	w.b = quicwire.AppendVarintBytes(w.b, []byte(reason))
   540  	// We don't record CONNECTION_CLOSE frames in w.sent, since they are never acked or
   541  	// detected as lost.
   542  	return true
   543  }
   544  
   545  // appendConnectionCloseApplicationFrame appends a CONNECTION_CLOSE frame
   546  // carrying an application protocol error code.
   547  func (w *packetWriter) appendConnectionCloseApplicationFrame(code uint64, reason string) (added bool) {
   548  	if w.avail() < 1+quicwire.SizeVarint(code)+quicwire.SizeVarint(uint64(len(reason)))+len(reason) {
   549  		return false
   550  	}
   551  	w.b = append(w.b, frameTypeConnectionCloseApplication)
   552  	w.b = quicwire.AppendVarint(w.b, code)
   553  	w.b = quicwire.AppendVarintBytes(w.b, []byte(reason))
   554  	// We don't record CONNECTION_CLOSE frames in w.sent, since they are never acked or
   555  	// detected as lost.
   556  	return true
   557  }
   558  
   559  func (w *packetWriter) appendHandshakeDoneFrame() (added bool) {
   560  	if w.avail() < 1 {
   561  		return false
   562  	}
   563  	w.b = append(w.b, frameTypeHandshakeDone)
   564  	w.sent.appendAckElicitingFrame(frameTypeHandshakeDone)
   565  	return true
   566  }
   567  

View as plain text