github.com/sagernet/quic-go@v0.43.1-beta.1/internal/wire/new_connection_id_frame.go (about)

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