// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT

package srtp

import (
	
	

	
)

/*
Simplified structure of SRTCP Packets:
- RTCP Header
- Payload
- AEAD Auth Tag - used by AEAD profiles only
- E flag and SRTCP Index
- MKI (optional)
- Auth Tag - used by non-AEAD profiles only
*/

const (
	maxSRTCPIndex = 0x7FFFFFFF

	srtcpHeaderSize     = 8
	srtcpIndexSize      = 4
	srtcpEncryptionFlag = 0x80
)

func ( *Context) (,  []byte) ([]byte, error) {
	,  := .cipher.AuthTagRTCPLen()
	if  != nil {
		return nil, 
	}
	,  := .cipher.AEADAuthTagLen()
	if  != nil {
		return nil, 
	}
	 := len(.sendMKI)

	// Verify that encrypted packet is long enough
	if len() < (srtcpHeaderSize +  + srtcpIndexSize +  + ) {
		return nil, fmt.Errorf("%w: %d", errTooShortRTCP, len())
	}

	 := .cipher.getRTCPIndex()
	 := binary.BigEndian.Uint32([4:])

	 := .getSRTCPSSRCState()
	,  := .replayDetector.Check(uint64())
	if ! {
		return nil, &duplicatedError{Proto: "srtcp", SSRC: , Index: }
	}

	 := .cipher
	if len(.mkis) > 0 {
		// Find cipher for MKI
		 := [len()-- : len()-]
		,  = .mkis[string()]
		if ! {
			return nil, ErrMKINotFound
		}
	}

	,  := .decryptRTCP(, , , )
	if  != nil {
		return nil, 
	}

	()

	return , nil
}

// DecryptRTCP decrypts a buffer that contains a RTCP packet.
func ( *Context) (,  []byte,  *rtcp.Header) ([]byte, error) {
	if  == nil {
		 = &rtcp.Header{}
	}

	if  := .Unmarshal();  != nil {
		return nil, 
	}

	return .decryptRTCP(, )
}

func ( *Context) (,  []byte) ([]byte, error) {
	if len() < srtcpHeaderSize {
		return nil, fmt.Errorf("%w: %d", errTooShortRTCP, len())
	}

	 := binary.BigEndian.Uint32([4:])
	 := .getSRTCPSSRCState()

	if .srtcpIndex >= maxSRTCPIndex {
		// ... when 2^48 SRTP packets or 2^31 SRTCP packets have been secured with the same key
		// (whichever occurs before), the key management MUST be called to provide new master key(s)
		// (previously stored and used keys MUST NOT be used again), or the session MUST be terminated.
		// https://www.rfc-editor.org/rfc/rfc3711#section-9.2
		return nil, errExceededMaxPackets
	}

	// We roll over early because MSB is used for marking as encrypted
	.srtcpIndex++

	return .cipher.encryptRTCP(, , .srtcpIndex, )
}

// EncryptRTCP Encrypts a RTCP packet.
func ( *Context) (,  []byte,  *rtcp.Header) ([]byte, error) {
	if  == nil {
		 = &rtcp.Header{}
	}

	if  := .Unmarshal();  != nil {
		return nil, 
	}

	return .encryptRTCP(, )
}