module DIAMETER_ts32_299_Templates {

/* (C) 2023 by sysmocom s.f.m.c. GmbH <info@sysmocom.de
 * All rights reserved.
 *
 * Released under the terms of GNU General Public License, Version 2 or
 * (at your option) any later version.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * Templates for AVPs and messages for TS 32.299
 */

import from General_Types all;
import from DIAMETER_Types all;
import from DIAMETER_Templates all;
import from Osmocom_Types all;
import from Misc_Helpers all;

/*******************************
 * Gy 3GPP TS 32.299 section 7
 *******************************/

/* Gy AID : 3GPP TS 32.299 7.1.6, RFC4006 3.1: c_DIAMETER_CREDIT_CONTROL_AID */

/* 3GPP TS 32.299  7.1.11 Result-Code AVP*/
type enumerated DIAMETER_ts32_229_Resultcode {
	/* transient */
	DIAMETER_END_USER_SERVICE_DENIED		(4010),
	DIAMETER_CREDIT_CONTROL_NOT_APPLICABLE 		(4011),
	DIAMETER_CREDIT_LIMIT_REACHED 			(4012),
	/* permanent */
	DIAMETER_AUTHORIZATION_REJECTED			(5003),
	DIAMETER_USER_UNKNOWN				(5030),
	DIAMETER_RATING_FAILED				(5031)
}

/* 3GPP TS 32.299 6.4.2 Credit-Control-Request */
template (present) PDU_DIAMETER
tr_DIA_Gy_CCR(template (present) DCC_NONE_CC_Request_Type req_type := INITIAL_REQUEST)
:= tr_DIAMETER(flags:='11000000'B, cmd_code:=Credit_Control,
	avps := superset(
		tr_AVP_SessionId,
		tr_AVP_OriginHost,
		tr_AVP_OriginRealm,
		tr_AVP_DestinationRealm,
		tr_AVP_AuthAppId(int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4)),
		tr_AVP_CcReqType(req_type),
		tr_AVP_CcReqNum(?)
	));

/* 3GPP TS 32.299 6.4.3 Credit-Control-Answer message */
template (value) PDU_DIAMETER
ts_DIA_Gy_CCA(template (value) UINT32 hbh_id, template (value) UINT32 ete_id,
	   template (value) octetstring sess_id,
	   template (value) DIAMETER_Resultcode res_code,
	   template (value) DCC_NONE_CC_Request_Type req_type,
	   template (value) AVP_Unsigned32 req_num)
:= ts_DIAMETER(flags:='01000000'B, cmd_code:=Credit_Control,
		app_id:=int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4), hbh_id:=hbh_id, ete_id:=ete_id,
	avps := {
		ts_AVP_SessionId(sess_id),
		ts_AVP_ResultCode(res_code),
		ts_AVP_OriginHost("ocs.localdomain"),
		ts_AVP_OriginRealm("localdomain"),
		ts_AVP_AuthAppId(int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4)),
		ts_AVP_CcReqType(req_type),
		ts_AVP_CcReqNum(req_num)//,
		// qos
		// default eps bearer qos
		// supported features
		// origin
	});
/* Same as ts_DIA_Gy_CCA, but with extra AVP to grant access for limited amount of seconds */
template (value) PDU_DIAMETER
ts_DIA_Gy_CCA_ValidityTime(template (value) UINT32 hbh_id, template (value) UINT32 ete_id,
	   template (value) octetstring sess_id,
	   template (value) DCC_NONE_CC_Request_Type req_type,
	   template (value) AVP_Unsigned32 req_num,
	   uint32_t validity_time)
:= ts_DIAMETER(flags:='01000000'B, cmd_code:=Credit_Control,
		app_id:=int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4), hbh_id:=hbh_id, ete_id:=ete_id,
	avps := {
		ts_AVP_SessionId(sess_id),
		ts_AVP_ResultCode(DIAMETER_SUCCESS),
		ts_AVP_OriginHost("ocs.localdomain"),
		ts_AVP_OriginRealm("localdomain"),
		ts_AVP_AuthAppId(int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4)),
		ts_AVP_CcReqType(req_type),
		ts_AVP_CcReqNum(req_num),
		ts_AVP_Multiple_Services_Credit_Control({
			ts_AVP_Validity_Time(validity_time),
			ts_AVP_Granted_Service_Unit({
				//ts_AVP_CC_Time(validity_time*2),
				ts_AVP_CC_Total_Octets(1000)
				})
			})
		//,
		// qos
		// default eps bearer qos
		// supported features
		// origin
	});
/* Same as ts_DIA_Gy_CCA_ValidityTime, but with extra AVP to grant access for limited amount of octets */
template (value) PDU_DIAMETER
ts_DIA_Gy_CCA_ValidityTimeVolumeThreshold(template (value) UINT32 hbh_id, template (value) UINT32 ete_id,
	   template (value) octetstring sess_id,
	   template (value) DCC_NONE_CC_Request_Type req_type,
	   template (value) AVP_Unsigned32 req_num,
	   uint32_t validity_time,
	   uint32_t volume_quota,
	   uint32_t volume_threhsold := 0)
:= ts_DIAMETER(flags:='01000000'B, cmd_code:=Credit_Control,
		app_id:=int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4), hbh_id:=hbh_id, ete_id:=ete_id,
	avps := {
		ts_AVP_SessionId(sess_id),
		ts_AVP_ResultCode(DIAMETER_SUCCESS),
		ts_AVP_OriginHost("ocs.localdomain"),
		ts_AVP_OriginRealm("localdomain"),
		ts_AVP_AuthAppId(int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4)),
		ts_AVP_CcReqType(req_type),
		ts_AVP_CcReqNum(req_num),
		ts_AVP_Multiple_Services_Credit_Control({
			ts_AVP_Validity_Time(validity_time),
			ts_AVP_Granted_Service_Unit({
				ts_AVP_CC_Total_Octets(volume_quota)
				}),
			ts_AVP_3GPP_VolumeQuotaThreshold(volume_threhsold)
			})
		//,
		// qos
		// default eps bearer qos
		// supported features
		// origin
	});

function f_validate_gy_cc_report(PDU_DIAMETER rx_dia, template (present) DCA_3GPP_Reporting_Reason repreason_exp := ?,
				 template (present) integer cc_time_exp := ?,
				 template (present) integer cc_in_oct_exp := ?,
				 template (present) integer cc_out_oct_exp := ?)
{
	var AVP multi_services_cc, used_service_unit;
	var AVP_Grouped multi_services_cc_data, used_service_unit_data;
	var template (omit) AVP repreason_tpl;
	var AVP repreason, cc_time, cc_in_oct, cc_out_oct;

	multi_services_cc := f_DIAMETER_get_avp_or_fail(rx_dia, c_AVP_Code_DCC_NONE_Multiple_Services_Credit_Control);
	multi_services_cc_data := valueof(multi_services_cc.avp_data.avp_DCC_NONE_Multiple_Services_Credit_Control);

	used_service_unit := f_AVP_Grouped_get_avp_or_fail(multi_services_cc_data, c_AVP_Code_DCC_NONE_Used_Service_Unit);
	used_service_unit_data := valueof(used_service_unit.avp_data.avp_DCC_NONE_Used_Service_Unit);

	/* Reporting-Reason can be either inside Multiple-Services-Credit-Control or inside Used-Service-Unit */
	repreason_tpl := f_AVP_Grouped_get_avp(multi_services_cc_data, c_AVP_Code_DCA_3GPP_Reporting_Reason);
	if (istemplatekind(repreason_tpl, "omit")) {
		repreason := f_AVP_Grouped_get_avp_or_fail(used_service_unit_data, c_AVP_Code_DCA_3GPP_Reporting_Reason);
	} else {
		repreason := valueof(repreason_tpl);
	}
	if (not match(repreason.avp_data.avp_DCA_3GPP_Reporting_Reason, repreason_exp)) {
		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
			log2str("3GPP-Reporting-Reason mismatch ", repreason, " vs exp ", repreason_exp));
	}

	cc_time := f_AVP_Grouped_get_avp_or_fail(used_service_unit_data, c_AVP_Code_DCC_NONE_CC_Time);
	if (not match(oct2int(cc_time.avp_data.avp_DCC_NONE_CC_Time), cc_time_exp)) {
		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
			log2str("3GPP-CC-Time mismatch ", cc_time, " vs exp ", cc_time_exp));
	}

	cc_in_oct := f_AVP_Grouped_get_avp_or_fail(used_service_unit_data, c_AVP_Code_DCC_NONE_CC_Input_Octets);
	if (not match(oct2int(cc_in_oct.avp_data.avp_DCC_NONE_CC_Input_Octets), cc_in_oct_exp)) {
		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
			log2str("3GPP-CC-Input-Octets mismatch ", cc_in_oct, " vs exp ", cc_in_oct_exp));
	}

	cc_out_oct := f_AVP_Grouped_get_avp_or_fail(used_service_unit_data, c_AVP_Code_DCC_NONE_CC_Output_Octets);
	if (not match(oct2int(cc_out_oct.avp_data.avp_DCC_NONE_CC_Output_Octets), cc_out_oct_exp)) {
		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
			log2str("3GPP-CC-Output-Octets mismatch ", cc_out_oct, " vs exp ", cc_out_oct_exp));
	}
}

} /* module */
