github.com/quic-go/quic-go@v0.44.0/internal/wire/new_connection_id_frame.go (about)

     1  package wire
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io"
     7  
     8  	"github.com/quic-go/quic-go/internal/protocol"
     9  	"github.com/quic-go/quic-go/quicvarint"
    10  )
    11  
    12  // A NewConnectionIDFrame is a NEW_CONNECTION_ID frame
    13  type NewConnectionIDFrame struct {
    14  	SequenceNumber      uint64
    15  	RetirePriorTo       uint64
    16  	ConnectionID        protocol.ConnectionID
    17  	StatelessResetToken protocol.StatelessResetToken
    18  }
    19  
    20  func parseNewConnectionIDFrame(b []byte, _ protocol.Version) (*NewConnectionIDFrame, int, error) {
    21  	startLen := len(b)
    22  	seq, l, err := quicvarint.Parse(b)
    23  	if err != nil {
    24  		return nil, 0, replaceUnexpectedEOF(err)
    25  	}
    26  	b = b[l:]
    27  	ret, l, err := quicvarint.Parse(b)
    28  	if err != nil {
    29  		return nil, 0, replaceUnexpectedEOF(err)
    30  	}
    31  	b = b[l:]
    32  	if ret > seq {
    33  		//nolint:stylecheck
    34  		return nil, 0, fmt.Errorf("Retire Prior To value (%d) larger than Sequence Number (%d)", ret, seq)
    35  	}
    36  	if len(b) == 0 {
    37  		return nil, 0, io.EOF
    38  	}
    39  	connIDLen := int(b[0])
    40  	b = b[1:]
    41  	if connIDLen == 0 {
    42  		return nil, 0, errors.New("invalid zero-length connection ID")
    43  	}
    44  	if connIDLen > protocol.MaxConnIDLen {
    45  		return nil, 0, protocol.ErrInvalidConnectionIDLen
    46  	}
    47  	if len(b) < connIDLen {
    48  		return nil, 0, io.EOF
    49  	}
    50  	frame := &NewConnectionIDFrame{
    51  		SequenceNumber: seq,
    52  		RetirePriorTo:  ret,
    53  		ConnectionID:   protocol.ParseConnectionID(b[:connIDLen]),
    54  	}
    55  	b = b[connIDLen:]
    56  	if len(b) < len(frame.StatelessResetToken) {
    57  		return nil, 0, io.EOF
    58  	}
    59  	copy(frame.StatelessResetToken[:], b)
    60  	return frame, startLen - len(b) + len(frame.StatelessResetToken), nil
    61  }
    62  
    63  func (f *NewConnectionIDFrame) Append(b []byte, _ protocol.Version) ([]byte, error) {
    64  	b = append(b, newConnectionIDFrameType)
    65  	b = quicvarint.Append(b, f.SequenceNumber)
    66  	b = quicvarint.Append(b, f.RetirePriorTo)
    67  	connIDLen := f.ConnectionID.Len()
    68  	if connIDLen > protocol.MaxConnIDLen {
    69  		return nil, fmt.Errorf("invalid connection ID length: %d", connIDLen)
    70  	}
    71  	b = append(b, uint8(connIDLen))
    72  	b = append(b, f.ConnectionID.Bytes()...)
    73  	b = append(b, f.StatelessResetToken[:]...)
    74  	return b, nil
    75  }
    76  
    77  // Length of a written frame
    78  func (f *NewConnectionIDFrame) Length(protocol.Version) protocol.ByteCount {
    79  	return 1 + protocol.ByteCount(quicvarint.Len(f.SequenceNumber)+quicvarint.Len(f.RetirePriorTo)+1 /* connection ID length */ +f.ConnectionID.Len()) + 16
    80  }