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 := min(w.pktLim, n)
   227  	if len(w.b) >= lim {
   228  		return
   229  	}
   230  	for len(w.b) < lim {
   231  		w.b = append(w.b, frameTypePadding)
   232  	}
   233  	// Packets are considered in flight when they contain a PADDING frame.
   234  	// https://www.rfc-editor.org/rfc/rfc9002.html#section-2-3.6.1
   235  	w.sent.inFlight = true
   236  }
   237  
   238  func (w *packetWriter) appendPingFrame() (added bool) {
   239  	if len(w.b) >= w.pktLim {
   240  		return false
   241  	}
   242  	w.b = append(w.b, frameTypePing)
   243  	w.sent.markAckEliciting() // no need to record the frame itself
   244  	return true
   245  }
   246  
   247  // appendAckFrame appends an ACK frame to the payload.
   248  // It includes at least the most recent range in the rangeset
   249  // (the range with the largest packet numbers),
   250  // followed by as many additional ranges as fit within the packet.
   251  //
   252  // We always place ACK frames at the start of packets,
   253  // we limit the number of ack ranges retained, and
   254  // we set a minimum packet payload size.
   255  // As a result, appendAckFrame will rarely if ever drop ranges
   256  // in practice.
   257  //
   258  // In the event that ranges are dropped, the impact is limited
   259  // to the peer potentially failing to receive an acknowledgement
   260  // for an older packet during a period of high packet loss or
   261  // reordering. This may result in unnecessary retransmissions.
   262  func (w *packetWriter) appendAckFrame(seen rangeset[packetNumber], delay unscaledAckDelay, ecn ecnCounts) (added bool) {
   263  	if len(seen) == 0 {
   264  		return false
   265  	}
   266  	var (
   267  		largest    = uint64(seen.max())
   268  		firstRange = uint64(seen[len(seen)-1].size() - 1)
   269  	)
   270  	var ecnLen int
   271  	ackType := byte(frameTypeAck)
   272  	if (ecn != ecnCounts{}) {
   273  		// "Even if an endpoint does not set an ECT field in packets it sends,
   274  		// the endpoint MUST provide feedback about ECN markings it receives, if
   275  		// these are accessible."
   276  		// https://www.rfc-editor.org/rfc/rfc9000.html#section-13.4.1-2
   277  		ecnLen = quicwire.SizeVarint(uint64(ecn.ce)) + quicwire.SizeVarint(uint64(ecn.t0)) + quicwire.SizeVarint(uint64(ecn.t1))
   278  		ackType = frameTypeAckECN
   279  	}
   280  	if w.avail() < 1+quicwire.SizeVarint(largest)+quicwire.SizeVarint(uint64(delay))+1+quicwire.SizeVarint(firstRange)+ecnLen {
   281  		return false
   282  	}
   283  	w.b = append(w.b, ackType)
   284  	w.b = quicwire.AppendVarint(w.b, largest)
   285  	w.b = quicwire.AppendVarint(w.b, uint64(delay))
   286  	// The range count is technically a varint, but we'll reserve a single byte for it
   287  	// and never add more than 62 ranges (the maximum varint that fits in a byte).
   288  	rangeCountOff := len(w.b)
   289  	w.b = append(w.b, 0)
   290  	w.b = quicwire.AppendVarint(w.b, firstRange)
   291  	rangeCount := byte(0)
   292  	for i := len(seen) - 2; i >= 0; i-- {
   293  		gap := uint64(seen[i+1].start - seen[i].end - 1)
   294  		size := uint64(seen[i].size() - 1)
   295  		if w.avail() < quicwire.SizeVarint(gap)+quicwire.SizeVarint(size)+ecnLen || rangeCount > 62 {
   296  			break
   297  		}
   298  		w.b = quicwire.AppendVarint(w.b, gap)
   299  		w.b = quicwire.AppendVarint(w.b, size)
   300  		rangeCount++
   301  	}
   302  	w.b[rangeCountOff] = rangeCount
   303  	if ackType == frameTypeAckECN {
   304  		w.b = quicwire.AppendVarint(w.b, uint64(ecn.t0))
   305  		w.b = quicwire.AppendVarint(w.b, uint64(ecn.t1))
   306  		w.b = quicwire.AppendVarint(w.b, uint64(ecn.ce))
   307  	}
   308  	w.sent.appendNonAckElicitingFrame(ackType)
   309  	w.sent.appendInt(uint64(seen.max()))
   310  	return true
   311  }
   312  
   313  func (w *packetWriter) appendNewTokenFrame(token []byte) (added bool) {
   314  	if w.avail() < 1+quicwire.SizeVarint(uint64(len(token)))+len(token) {
   315  		return false
   316  	}
   317  	w.b = append(w.b, frameTypeNewToken)
   318  	w.b = quicwire.AppendVarintBytes(w.b, token)
   319  	return true
   320  }
   321  
   322  func (w *packetWriter) appendResetStreamFrame(id streamID, code uint64, finalSize int64) (added bool) {
   323  	if w.avail() < 1+quicwire.SizeVarint(uint64(id))+quicwire.SizeVarint(code)+quicwire.SizeVarint(uint64(finalSize)) {
   324  		return false
   325  	}
   326  	w.b = append(w.b, frameTypeResetStream)
   327  	w.b = quicwire.AppendVarint(w.b, uint64(id))
   328  	w.b = quicwire.AppendVarint(w.b, code)
   329  	w.b = quicwire.AppendVarint(w.b, uint64(finalSize))
   330  	w.sent.appendAckElicitingFrame(frameTypeResetStream)
   331  	w.sent.appendInt(uint64(id))
   332  	return true
   333  }
   334  
   335  func (w *packetWriter) appendStopSendingFrame(id streamID, code uint64) (added bool) {
   336  	if w.avail() < 1+quicwire.SizeVarint(uint64(id))+quicwire.SizeVarint(code) {
   337  		return false
   338  	}
   339  	w.b = append(w.b, frameTypeStopSending)
   340  	w.b = quicwire.AppendVarint(w.b, uint64(id))
   341  	w.b = quicwire.AppendVarint(w.b, code)
   342  	w.sent.appendAckElicitingFrame(frameTypeStopSending)
   343  	w.sent.appendInt(uint64(id))
   344  	return true
   345  }
   346  
   347  // appendCryptoFrame appends a CRYPTO frame.
   348  // It returns a []byte into which the data should be written and whether a frame was added.
   349  // The returned []byte may be smaller than size if the packet cannot hold all the data.
   350  func (w *packetWriter) appendCryptoFrame(off int64, size int) (_ []byte, added bool) {
   351  	max := w.avail()
   352  	max -= 1                                 // frame type
   353  	max -= quicwire.SizeVarint(uint64(off))  // offset
   354  	max -= quicwire.SizeVarint(uint64(size)) // maximum length
   355  	if max <= 0 {
   356  		return nil, false
   357  	}
   358  	if max < size {
   359  		size = max
   360  	}
   361  	w.b = append(w.b, frameTypeCrypto)
   362  	w.b = quicwire.AppendVarint(w.b, uint64(off))
   363  	w.b = quicwire.AppendVarint(w.b, uint64(size))
   364  	start := len(w.b)
   365  	w.b = w.b[:start+size]
   366  	w.sent.appendAckElicitingFrame(frameTypeCrypto)
   367  	w.sent.appendOffAndSize(off, size)
   368  	return w.b[start:][:size], true
   369  }
   370  
   371  // appendStreamFrame appends a STREAM frame.
   372  // It returns a []byte into which the data should be written and whether a frame was added.
   373  // The returned []byte may be smaller than size if the packet cannot hold all the data.
   374  func (w *packetWriter) appendStreamFrame(id streamID, off int64, size int, fin bool) (_ []byte, added bool) {
   375  	typ := uint8(frameTypeStreamBase | streamLenBit)
   376  	max := w.avail()
   377  	max -= 1 // frame type
   378  	max -= quicwire.SizeVarint(uint64(id))
   379  	if off != 0 {
   380  		max -= quicwire.SizeVarint(uint64(off))
   381  		typ |= streamOffBit
   382  	}
   383  	max -= quicwire.SizeVarint(uint64(size)) // maximum length
   384  	if max < 0 || (max == 0 && size > 0) {
   385  		return nil, false
   386  	}
   387  	if max < size {
   388  		size = max
   389  	} else if fin {
   390  		typ |= streamFinBit
   391  	}
   392  	w.b = append(w.b, typ)
   393  	w.b = quicwire.AppendVarint(w.b, uint64(id))
   394  	if off != 0 {
   395  		w.b = quicwire.AppendVarint(w.b, uint64(off))
   396  	}
   397  	w.b = quicwire.AppendVarint(w.b, uint64(size))
   398  	start := len(w.b)
   399  	w.b = w.b[:start+size]
   400  	w.sent.appendAckElicitingFrame(typ & (frameTypeStreamBase | streamFinBit))
   401  	w.sent.appendInt(uint64(id))
   402  	w.sent.appendOffAndSize(off, size)
   403  	return w.b[start:][:size], true
   404  }
   405  
   406  func (w *packetWriter) appendMaxDataFrame(max int64) (added bool) {
   407  	if w.avail() < 1+quicwire.SizeVarint(uint64(max)) {
   408  		return false
   409  	}
   410  	w.b = append(w.b, frameTypeMaxData)
   411  	w.b = quicwire.AppendVarint(w.b, uint64(max))
   412  	w.sent.appendAckElicitingFrame(frameTypeMaxData)
   413  	return true
   414  }
   415  
   416  func (w *packetWriter) appendMaxStreamDataFrame(id streamID, max int64) (added bool) {
   417  	if w.avail() < 1+quicwire.SizeVarint(uint64(id))+quicwire.SizeVarint(uint64(max)) {
   418  		return false
   419  	}
   420  	w.b = append(w.b, frameTypeMaxStreamData)
   421  	w.b = quicwire.AppendVarint(w.b, uint64(id))
   422  	w.b = quicwire.AppendVarint(w.b, uint64(max))
   423  	w.sent.appendAckElicitingFrame(frameTypeMaxStreamData)
   424  	w.sent.appendInt(uint64(id))
   425  	return true
   426  }
   427  
   428  func (w *packetWriter) appendMaxStreamsFrame(streamType streamType, max int64) (added bool) {
   429  	if w.avail() < 1+quicwire.SizeVarint(uint64(max)) {
   430  		return false
   431  	}
   432  	var typ byte
   433  	if streamType == bidiStream {
   434  		typ = frameTypeMaxStreamsBidi
   435  	} else {
   436  		typ = frameTypeMaxStreamsUni
   437  	}
   438  	w.b = append(w.b, typ)
   439  	w.b = quicwire.AppendVarint(w.b, uint64(max))
   440  	w.sent.appendAckElicitingFrame(typ)
   441  	return true
   442  }
   443  
   444  func (w *packetWriter) appendDataBlockedFrame(max int64) (added bool) {
   445  	if w.avail() < 1+quicwire.SizeVarint(uint64(max)) {
   446  		return false
   447  	}
   448  	w.b = append(w.b, frameTypeDataBlocked)
   449  	w.b = quicwire.AppendVarint(w.b, uint64(max))
   450  	w.sent.appendAckElicitingFrame(frameTypeDataBlocked)
   451  	return true
   452  }
   453  
   454  func (w *packetWriter) appendStreamDataBlockedFrame(id streamID, max int64) (added bool) {
   455  	if w.avail() < 1+quicwire.SizeVarint(uint64(id))+quicwire.SizeVarint(uint64(max)) {
   456  		return false
   457  	}
   458  	w.b = append(w.b, frameTypeStreamDataBlocked)
   459  	w.b = quicwire.AppendVarint(w.b, uint64(id))
   460  	w.b = quicwire.AppendVarint(w.b, uint64(max))
   461  	w.sent.appendAckElicitingFrame(frameTypeStreamDataBlocked)
   462  	w.sent.appendInt(uint64(id))
   463  	return true
   464  }
   465  
   466  func (w *packetWriter) appendStreamsBlockedFrame(typ streamType, max int64) (added bool) {
   467  	if w.avail() < 1+quicwire.SizeVarint(uint64(max)) {
   468  		return false
   469  	}
   470  	var ftype byte
   471  	if typ == bidiStream {
   472  		ftype = frameTypeStreamsBlockedBidi
   473  	} else {
   474  		ftype = frameTypeStreamsBlockedUni
   475  	}
   476  	w.b = append(w.b, ftype)
   477  	w.b = quicwire.AppendVarint(w.b, uint64(max))
   478  	w.sent.appendAckElicitingFrame(ftype)
   479  	return true
   480  }
   481  
   482  func (w *packetWriter) appendNewConnectionIDFrame(seq, retirePriorTo int64, connID []byte, token [16]byte) (added bool) {
   483  	if w.avail() < 1+quicwire.SizeVarint(uint64(seq))+quicwire.SizeVarint(uint64(retirePriorTo))+1+len(connID)+len(token) {
   484  		return false
   485  	}
   486  	w.b = append(w.b, frameTypeNewConnectionID)
   487  	w.b = quicwire.AppendVarint(w.b, uint64(seq))
   488  	w.b = quicwire.AppendVarint(w.b, uint64(retirePriorTo))
   489  	w.b = quicwire.AppendUint8Bytes(w.b, connID)
   490  	w.b = append(w.b, token[:]...)
   491  	w.sent.appendAckElicitingFrame(frameTypeNewConnectionID)
   492  	w.sent.appendInt(uint64(seq))
   493  	return true
   494  }
   495  
   496  func (w *packetWriter) appendRetireConnectionIDFrame(seq int64) (added bool) {
   497  	if w.avail() < 1+quicwire.SizeVarint(uint64(seq)) {
   498  		return false
   499  	}
   500  	w.b = append(w.b, frameTypeRetireConnectionID)
   501  	w.b = quicwire.AppendVarint(w.b, uint64(seq))
   502  	w.sent.appendAckElicitingFrame(frameTypeRetireConnectionID)
   503  	w.sent.appendInt(uint64(seq))
   504  	return true
   505  }
   506  
   507  func (w *packetWriter) appendPathChallengeFrame(data pathChallengeData) (added bool) {
   508  	if w.avail() < 1+8 {
   509  		return false
   510  	}
   511  	w.b = append(w.b, frameTypePathChallenge)
   512  	w.b = append(w.b, data[:]...)
   513  	w.sent.markAckEliciting() // no need to record the frame itself
   514  	return true
   515  }
   516  
   517  func (w *packetWriter) appendPathResponseFrame(data pathChallengeData) (added bool) {
   518  	if w.avail() < 1+8 {
   519  		return false
   520  	}
   521  	w.b = append(w.b, frameTypePathResponse)
   522  	w.b = append(w.b, data[:]...)
   523  	w.sent.markAckEliciting() // no need to record the frame itself
   524  	return true
   525  }
   526  
   527  // appendConnectionCloseTransportFrame appends a CONNECTION_CLOSE frame
   528  // carrying a transport error code.
   529  func (w *packetWriter) appendConnectionCloseTransportFrame(code transportError, frameType uint64, reason string) (added bool) {
   530  	if w.avail() < 1+quicwire.SizeVarint(uint64(code))+quicwire.SizeVarint(frameType)+quicwire.SizeVarint(uint64(len(reason)))+len(reason) {
   531  		return false
   532  	}
   533  	w.b = append(w.b, frameTypeConnectionCloseTransport)
   534  	w.b = quicwire.AppendVarint(w.b, uint64(code))
   535  	w.b = quicwire.AppendVarint(w.b, frameType)
   536  	w.b = quicwire.AppendVarintBytes(w.b, []byte(reason))
   537  	// We don't record CONNECTION_CLOSE frames in w.sent, since they are never acked or
   538  	// detected as lost.
   539  	return true
   540  }
   541  
   542  // appendConnectionCloseApplicationFrame appends a CONNECTION_CLOSE frame
   543  // carrying an application protocol error code.
   544  func (w *packetWriter) appendConnectionCloseApplicationFrame(code uint64, reason string) (added bool) {
   545  	if w.avail() < 1+quicwire.SizeVarint(code)+quicwire.SizeVarint(uint64(len(reason)))+len(reason) {
   546  		return false
   547  	}
   548  	w.b = append(w.b, frameTypeConnectionCloseApplication)
   549  	w.b = quicwire.AppendVarint(w.b, code)
   550  	w.b = quicwire.AppendVarintBytes(w.b, []byte(reason))
   551  	// We don't record CONNECTION_CLOSE frames in w.sent, since they are never acked or
   552  	// detected as lost.
   553  	return true
   554  }
   555  
   556  func (w *packetWriter) appendHandshakeDoneFrame() (added bool) {
   557  	if w.avail() < 1 {
   558  		return false
   559  	}
   560  	w.b = append(w.b, frameTypeHandshakeDone)
   561  	w.sent.appendAckElicitingFrame(frameTypeHandshakeDone)
   562  	return true
   563  }
   564  

View as plain text