golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/quic/packet.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  	"encoding/binary"
    11  	"fmt"
    12  )
    13  
    14  // packetType is a QUIC packet type.
    15  // https://www.rfc-editor.org/rfc/rfc9000.html#section-17
    16  type packetType byte
    17  
    18  const (
    19  	packetTypeInvalid = packetType(iota)
    20  	packetTypeInitial
    21  	packetType0RTT
    22  	packetTypeHandshake
    23  	packetTypeRetry
    24  	packetType1RTT
    25  	packetTypeVersionNegotiation
    26  )
    27  
    28  func (p packetType) String() string {
    29  	switch p {
    30  	case packetTypeInitial:
    31  		return "Initial"
    32  	case packetType0RTT:
    33  		return "0-RTT"
    34  	case packetTypeHandshake:
    35  		return "Handshake"
    36  	case packetTypeRetry:
    37  		return "Retry"
    38  	case packetType1RTT:
    39  		return "1-RTT"
    40  	}
    41  	return fmt.Sprintf("unknown packet type %v", byte(p))
    42  }
    43  
    44  func (p packetType) qlogString() string {
    45  	switch p {
    46  	case packetTypeInitial:
    47  		return "initial"
    48  	case packetType0RTT:
    49  		return "0RTT"
    50  	case packetTypeHandshake:
    51  		return "handshake"
    52  	case packetTypeRetry:
    53  		return "retry"
    54  	case packetType1RTT:
    55  		return "1RTT"
    56  	}
    57  	return "unknown"
    58  }
    59  
    60  // Bits set in the first byte of a packet.
    61  const (
    62  	headerFormLong   = 0x80 // https://www.rfc-editor.org/rfc/rfc9000.html#section-17.2-3.2.1
    63  	headerFormShort  = 0x00 // https://www.rfc-editor.org/rfc/rfc9000.html#section-17.3.1-4.2.1
    64  	fixedBit         = 0x40 // https://www.rfc-editor.org/rfc/rfc9000.html#section-17.2-3.4.1
    65  	reservedLongBits = 0x0c // https://www.rfc-editor.org/rfc/rfc9000#section-17.2-8.2.1
    66  	reserved1RTTBits = 0x18 // https://www.rfc-editor.org/rfc/rfc9000#section-17.3.1-4.8.1
    67  	keyPhaseBit      = 0x04 // https://www.rfc-editor.org/rfc/rfc9000#section-17.3.1-4.10.1
    68  )
    69  
    70  // Long Packet Type bits.
    71  // https://www.rfc-editor.org/rfc/rfc9000.html#section-17.2-3.6.1
    72  const (
    73  	longPacketTypeInitial   = 0 << 4
    74  	longPacketType0RTT      = 1 << 4
    75  	longPacketTypeHandshake = 2 << 4
    76  	longPacketTypeRetry     = 3 << 4
    77  )
    78  
    79  // Frame types.
    80  // https://www.rfc-editor.org/rfc/rfc9000.html#section-19
    81  const (
    82  	frameTypePadding                    = 0x00
    83  	frameTypePing                       = 0x01
    84  	frameTypeAck                        = 0x02
    85  	frameTypeAckECN                     = 0x03
    86  	frameTypeResetStream                = 0x04
    87  	frameTypeStopSending                = 0x05
    88  	frameTypeCrypto                     = 0x06
    89  	frameTypeNewToken                   = 0x07
    90  	frameTypeStreamBase                 = 0x08 // low three bits carry stream flags
    91  	frameTypeMaxData                    = 0x10
    92  	frameTypeMaxStreamData              = 0x11
    93  	frameTypeMaxStreamsBidi             = 0x12
    94  	frameTypeMaxStreamsUni              = 0x13
    95  	frameTypeDataBlocked                = 0x14
    96  	frameTypeStreamDataBlocked          = 0x15
    97  	frameTypeStreamsBlockedBidi         = 0x16
    98  	frameTypeStreamsBlockedUni          = 0x17
    99  	frameTypeNewConnectionID            = 0x18
   100  	frameTypeRetireConnectionID         = 0x19
   101  	frameTypePathChallenge              = 0x1a
   102  	frameTypePathResponse               = 0x1b
   103  	frameTypeConnectionCloseTransport   = 0x1c
   104  	frameTypeConnectionCloseApplication = 0x1d
   105  	frameTypeHandshakeDone              = 0x1e
   106  )
   107  
   108  // The low three bits of STREAM frames.
   109  // https://www.rfc-editor.org/rfc/rfc9000.html#section-19.8
   110  const (
   111  	streamOffBit = 0x04
   112  	streamLenBit = 0x02
   113  	streamFinBit = 0x01
   114  )
   115  
   116  // Maximum length of a connection ID.
   117  const maxConnIDLen = 20
   118  
   119  // isLongHeader returns true if b is the first byte of a long header.
   120  func isLongHeader(b byte) bool {
   121  	return b&headerFormLong == headerFormLong
   122  }
   123  
   124  // getPacketType returns the type of a packet.
   125  func getPacketType(b []byte) packetType {
   126  	if len(b) == 0 {
   127  		return packetTypeInvalid
   128  	}
   129  	if !isLongHeader(b[0]) {
   130  		if b[0]&fixedBit != fixedBit {
   131  			return packetTypeInvalid
   132  		}
   133  		return packetType1RTT
   134  	}
   135  	if len(b) < 5 {
   136  		return packetTypeInvalid
   137  	}
   138  	if b[1] == 0 && b[2] == 0 && b[3] == 0 && b[4] == 0 {
   139  		// Version Negotiation packets don't necessarily set the fixed bit.
   140  		return packetTypeVersionNegotiation
   141  	}
   142  	if b[0]&fixedBit != fixedBit {
   143  		return packetTypeInvalid
   144  	}
   145  	switch b[0] & 0x30 {
   146  	case longPacketTypeInitial:
   147  		return packetTypeInitial
   148  	case longPacketType0RTT:
   149  		return packetType0RTT
   150  	case longPacketTypeHandshake:
   151  		return packetTypeHandshake
   152  	case longPacketTypeRetry:
   153  		return packetTypeRetry
   154  	}
   155  	return packetTypeInvalid
   156  }
   157  
   158  // dstConnIDForDatagram returns the destination connection ID field of the
   159  // first QUIC packet in a datagram.
   160  func dstConnIDForDatagram(pkt []byte) (id []byte, ok bool) {
   161  	if len(pkt) < 1 {
   162  		return nil, false
   163  	}
   164  	var n int
   165  	var b []byte
   166  	if isLongHeader(pkt[0]) {
   167  		if len(pkt) < 6 {
   168  			return nil, false
   169  		}
   170  		n = int(pkt[5])
   171  		b = pkt[6:]
   172  	} else {
   173  		n = connIDLen
   174  		b = pkt[1:]
   175  	}
   176  	if len(b) < n {
   177  		return nil, false
   178  	}
   179  	return b[:n], true
   180  }
   181  
   182  // parseVersionNegotiation parses a Version Negotiation packet.
   183  // The returned versions is a slice of big-endian uint32s.
   184  // It returns (nil, nil, nil) for an invalid packet.
   185  func parseVersionNegotiation(pkt []byte) (dstConnID, srcConnID, versions []byte) {
   186  	p, ok := parseGenericLongHeaderPacket(pkt)
   187  	if !ok {
   188  		return nil, nil, nil
   189  	}
   190  	if len(p.data)%4 != 0 {
   191  		return nil, nil, nil
   192  	}
   193  	return p.dstConnID, p.srcConnID, p.data
   194  }
   195  
   196  // appendVersionNegotiation appends a Version Negotiation packet to pkt,
   197  // returning the result.
   198  func appendVersionNegotiation(pkt, dstConnID, srcConnID []byte, versions ...uint32) []byte {
   199  	pkt = append(pkt, headerFormLong|fixedBit) // header byte
   200  	pkt = append(pkt, 0, 0, 0, 0)              // Version (0 for Version Negotiation)
   201  	pkt = appendUint8Bytes(pkt, dstConnID)     // Destination Connection ID
   202  	pkt = appendUint8Bytes(pkt, srcConnID)     // Source Connection ID
   203  	for _, v := range versions {
   204  		pkt = binary.BigEndian.AppendUint32(pkt, v) // Supported Version
   205  	}
   206  	return pkt
   207  }
   208  
   209  // A longPacket is a long header packet.
   210  type longPacket struct {
   211  	ptype     packetType
   212  	version   uint32
   213  	num       packetNumber
   214  	dstConnID []byte
   215  	srcConnID []byte
   216  	payload   []byte
   217  
   218  	// The extra data depends on the packet type:
   219  	//   Initial: Token.
   220  	//   Retry: Retry token and integrity tag.
   221  	extra []byte
   222  }
   223  
   224  // A shortPacket is a short header (1-RTT) packet.
   225  type shortPacket struct {
   226  	num     packetNumber
   227  	payload []byte
   228  }
   229  
   230  // A genericLongPacket is a long header packet of an arbitrary QUIC version.
   231  // https://www.rfc-editor.org/rfc/rfc8999#section-5.1
   232  type genericLongPacket struct {
   233  	version   uint32
   234  	dstConnID []byte
   235  	srcConnID []byte
   236  	data      []byte
   237  }
   238  
   239  func parseGenericLongHeaderPacket(b []byte) (p genericLongPacket, ok bool) {
   240  	if len(b) < 5 || !isLongHeader(b[0]) {
   241  		return genericLongPacket{}, false
   242  	}
   243  	b = b[1:]
   244  	// Version (32),
   245  	var n int
   246  	p.version, n = consumeUint32(b)
   247  	if n < 0 {
   248  		return genericLongPacket{}, false
   249  	}
   250  	b = b[n:]
   251  	// Destination Connection ID Length (8),
   252  	// Destination Connection ID (0..2048),
   253  	p.dstConnID, n = consumeUint8Bytes(b)
   254  	if n < 0 || len(p.dstConnID) > 2048/8 {
   255  		return genericLongPacket{}, false
   256  	}
   257  	b = b[n:]
   258  	// Source Connection ID Length (8),
   259  	// Source Connection ID (0..2048),
   260  	p.srcConnID, n = consumeUint8Bytes(b)
   261  	if n < 0 || len(p.dstConnID) > 2048/8 {
   262  		return genericLongPacket{}, false
   263  	}
   264  	b = b[n:]
   265  	p.data = b
   266  	return p, true
   267  }