package quic

import (
	
	

	
	
	
	
)

type headerDecryptor interface {
	DecryptHeader(sample []byte, firstByte *byte, pnBytes []byte)
}

type headerParseError struct {
	err error
}

func ( *headerParseError) () error {
	return .err
}

func ( *headerParseError) () string {
	return .err.Error()
}

type unpackedPacket struct {
	hdr             *wire.ExtendedHeader
	encryptionLevel protocol.EncryptionLevel
	data            []byte
}

// The packetUnpacker unpacks QUIC packets.
type packetUnpacker struct {
	cs handshake.CryptoSetup

	shortHdrConnIDLen int
}

var _ unpacker = &packetUnpacker{}

func newPacketUnpacker( handshake.CryptoSetup,  int) *packetUnpacker {
	return &packetUnpacker{
		cs:                ,
		shortHdrConnIDLen: ,
	}
}

// UnpackLongHeader unpacks a Long Header packet.
// If the reserved bits are invalid, the error is wire.ErrInvalidReservedBits.
// If any other error occurred when parsing the header, the error is of type headerParseError.
// If decrypting the payload fails for any reason, the error is the error returned by the AEAD.
func ( *packetUnpacker) ( *wire.Header,  []byte) (*unpackedPacket, error) {
	var  protocol.EncryptionLevel
	var  *wire.ExtendedHeader
	var  []byte
	//nolint:exhaustive // Retry packets can't be unpacked.
	switch .Type {
	case protocol.PacketTypeInitial:
		 = protocol.EncryptionInitial
		,  := .cs.GetInitialOpener()
		if  != nil {
			return nil, 
		}
		, ,  = .unpackLongHeaderPacket(, , )
		if  != nil {
			return nil, 
		}
	case protocol.PacketTypeHandshake:
		 = protocol.EncryptionHandshake
		,  := .cs.GetHandshakeOpener()
		if  != nil {
			return nil, 
		}
		, ,  = .unpackLongHeaderPacket(, , )
		if  != nil {
			return nil, 
		}
	case protocol.PacketType0RTT:
		 = protocol.Encryption0RTT
		,  := .cs.Get0RTTOpener()
		if  != nil {
			return nil, 
		}
		, ,  = .unpackLongHeaderPacket(, , )
		if  != nil {
			return nil, 
		}
	default:
		return nil, fmt.Errorf("unknown packet type: %s", .Type)
	}

	if len() == 0 {
		return nil, &qerr.TransportError{
			ErrorCode:    qerr.ProtocolViolation,
			ErrorMessage: "empty packet",
		}
	}

	return &unpackedPacket{
		hdr:             ,
		encryptionLevel: ,
		data:            ,
	}, nil
}

func ( *packetUnpacker) ( time.Time,  []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error) {
	,  := .cs.Get1RTTOpener()
	if  != nil {
		return 0, 0, 0, nil, 
	}
	, , , ,  := .unpackShortHeaderPacket(, , )
	if  != nil {
		return 0, 0, 0, nil, 
	}
	if len() == 0 {
		return 0, 0, 0, nil, &qerr.TransportError{
			ErrorCode:    qerr.ProtocolViolation,
			ErrorMessage: "empty packet",
		}
	}
	return , , , , nil
}

func ( *packetUnpacker) ( handshake.LongHeaderOpener,  *wire.Header,  []byte) (*wire.ExtendedHeader, []byte, error) {
	,  := .unpackLongHeader(, , )
	// If the reserved bits are set incorrectly, we still need to continue unpacking.
	// This avoids a timing side-channel, which otherwise might allow an attacker
	// to gain information about the header encryption.
	if  != nil &&  != wire.ErrInvalidReservedBits {
		return nil, nil, 
	}
	 := .ParsedLen()
	.PacketNumber = .DecodePacketNumber(.PacketNumber, .PacketNumberLen)
	,  := .Open([:], [:], .PacketNumber, [:])
	if  != nil {
		return nil, nil, 
	}
	if  != nil {
		return nil, nil, 
	}
	return , , nil
}

func ( *packetUnpacker) ( handshake.ShortHeaderOpener,  time.Time,  []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error) {
	, , , ,  := .unpackShortHeader(, )
	// If the reserved bits are set incorrectly, we still need to continue unpacking.
	// This avoids a timing side-channel, which otherwise might allow an attacker
	// to gain information about the header encryption.
	if  != nil &&  != wire.ErrInvalidReservedBits {
		return 0, 0, 0, nil, &headerParseError{}
	}
	 = .DecodePacketNumber(, )
	,  := .Open([:], [:], , , , [:])
	if  != nil {
		return 0, 0, 0, nil, 
	}
	return , , , , 
}

func ( *packetUnpacker) ( headerDecryptor,  []byte) (int, protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, error) {
	 := 1 /* first header byte */ + .shortHdrConnIDLen
	if len() < +4+16 {
		return 0, 0, 0, 0, fmt.Errorf("packet too small, expected at least 20 bytes after the header, got %d", len()-)
	}
	 := make([]byte, 4)
	copy(, [:+4])
	// 2. decrypt the header, assuming a 4 byte packet number
	.DecryptHeader(
		[+4:+4+16],
		&[0],
		[:+4],
	)
	// 3. parse the header (and learn the actual length of the packet number)
	, , , ,  := wire.ParseShortHeader(, .shortHdrConnIDLen)
	if  != nil &&  != wire.ErrInvalidReservedBits {
		return , , , , 
	}
	// 4. if the packet number is shorter than 4 bytes, replace the remaining bytes with the copy we saved earlier
	if  != protocol.PacketNumberLen4 {
		copy([+int():+4], [int():])
	}
	return , , , , 
}

// The error is either nil, a wire.ErrInvalidReservedBits or of type headerParseError.
func ( *packetUnpacker) ( headerDecryptor,  *wire.Header,  []byte) (*wire.ExtendedHeader, error) {
	,  := unpackLongHeader(, , )
	if  != nil &&  != wire.ErrInvalidReservedBits {
		return nil, &headerParseError{err: }
	}
	return , 
}

func unpackLongHeader( headerDecryptor,  *wire.Header,  []byte) (*wire.ExtendedHeader, error) {
	 := .ParsedLen()
	if protocol.ByteCount(len()) < +4+16 {
		return nil, fmt.Errorf("packet too small, expected at least 20 bytes after the header, got %d", protocol.ByteCount(len())-)
	}
	// The packet number can be up to 4 bytes long, but we won't know the length until we decrypt it.
	// 1. save a copy of the 4 bytes
	 := make([]byte, 4)
	copy(, [:+4])
	// 2. decrypt the header, assuming a 4 byte packet number
	.DecryptHeader(
		[+4:+4+16],
		&[0],
		[:+4],
	)
	// 3. parse the header (and learn the actual length of the packet number)
	,  := .ParseExtended()
	if  != nil &&  != wire.ErrInvalidReservedBits {
		return nil, 
	}
	// 4. if the packet number is shorter than 4 bytes, replace the remaining bytes with the copy we saved earlier
	if .PacketNumberLen != protocol.PacketNumberLen4 {
		copy([.ParsedLen():+4], [int(.PacketNumberLen):])
	}
	return , 
}