######################################################################
# Originating, Initial Requests
######################################################################
route[MO]
{
	# Strip Transport from RURI:
	$ru = $(ru{re.subst,/;transport=[A-Za-z]*//g});
	xnotice("PCSCF MO: \n Destination URI: $du\n Request URI: $ru\n");
    xnotice("Source IP and Port: ($si:$sp)\n Route-URI: $route_uri\n");
    xnotice("Received IP and Port: ($Ri:$Rp)\n");
    xnotice("Contact header: $ct\n");

	# Process route headers, if any:
	loose_route();
	if (!pcscf_is_registered("location")) {
		send_reply("403", "Forbidden - You must register first with a S-CSCF");
		exit;
	}

	# We do not trust the user, let's remove the P-Asserted-Identity, if any:
	remove_hf("P-Asserted-Identity");
	remove_hf("P-Preferred-Identity");

	# Add P-Charging-Vector
	sip_p_charging_vector("g");

	if (is_present_hf("P-Preferred-Identity") && pcscf_assert_identity("location", "$hdr(P-Preferred-Identity)") && $hdr(P-Preferred-Identity) =~ "sip:.*") {
		append_hf("P-Asserted-Identity: $hdr(P-Preferred-Identity)\r\n");
	} else if (is_present_hf("P-Asserted-Identity") && pcscf_assert_identity("location", "$hdr(P-Asserted-Identity)") && $hdr(P-Asserted-Identity) =~ "sip:.*") {
		append_hf("P-Asserted-Identity: $hdr(P-Asserted-Identity)\r\n");
	} else if (pcscf_assert_identity("location", "$(fu{tobody.uri})")) {
		# For broken SIP implementation in Samsung devices
		if ($fu =~ "tel:.*") {
			$var(new_hdr) = $(fu{tobody.uri}) + "@NETWORKNAME";
			$var(new_hdr) = $(var(new_hdr){re.subst,/tel:/sip:/g});
			append_hf("P-Asserted-Identity: <$var(new_hdr)>\r\n");
			$fu = $var(new_hdr);
		} else {
		append_hf("P-Asserted-Identity: <$(fu{tobody.uri})>\r\n");
		}
	} else {
		append_hf("P-Asserted-Identity: <$pcscf_asserted_identity>\r\n");
	}

	if (!pcscf_follows_service_routes("location")){
		#Variant 1 - deny access to the network
		#send_reply("400", "Bad Request - Not following indicated service routes");
		#break;

		#Variant 2 - enforce routes and let the dialog continue
		pcscf_force_service_routes("location");
	}

	# add IBCF/THIG route here if required
	# Check for "sec-agree" in the Require header:
	if (is_present_hf("Require") && $hdr(Require) =~ ".*sec-agree.*") {
		# Remove the old Require-Header:
		remove_hf("Require");
		# Replace ", sec-agree" with ""
		$var(new_hdr) = $(hdr(Require){re.subst,/[, ]*sec-agree//gi});
		if ($(var(new_hdr){s.len}) > 0) {
			append_hf("Require: $var(new_hdr)\r\n");
		}
	}

	# Check for "sec-agree" in the Proxy-Require header:
	if (is_present_hf("Proxy-Require") && $hdr(Proxy-Require) =~ ".*sec-agree.*") {
		# Remove the old Proxy-Require-Header:		
		remove_hf("Proxy-Require");
		# Replace ", sec-agree" with ""
		$var(new_hdr) = $(hdr(Proxy-Require){re.subst,/[, ]*sec-agree//gi});
		if ($(var(new_hdr){s.len}) > 0) {
			append_hf("Proxy-Require: $var(new_hdr)\r\n");
		}
        }
	remove_hf("Security-Verify");

#!ifdef TRF_FUNCTION
	$var(trf) = TRF_FUNCTION;
	# Check for "sec-agree" in the Proxy-Require header:
	if (is_present_hf("Feature-Caps")) {
		# Remove the old Proxy-Require-Header:		
		remove_hf("Feature-Caps");
		append_hf("Feature-Caps: $hdr(Feature-Caps);+g.3gpp.trf=\"<sip:$var(trf);lr>\"\r\n");
        } else {
		append_hf("Feature-Caps: *;+g.3gpp.trf=\"<sip:$var(trf);lr>\"\r\n");
	}
#!endif	
	# Add a visited Network-ID-Header:
	if (is_present_hf("P-Visited-Network-ID")) {
		$var(new_hdr) = "NETWORKNAME, "+$hdr(P-Visited-Network-ID);
		append_hf("P-Visited-Network-ID: $var(new_hdr)\r\n");
	} else {
		append_hf("P-Visited-Network-ID: NETWORKNAME\r\n");
	}
	set_dlg_profile("orig");
	t_on_reply("MO_reply");
}

######################################################################
# Replies to Originating Initial Requests
######################################################################
onreply_route[MO_reply] {
	xnotice("PCSCF MO_reply: \n Destination URI: $du\n Request URI: $ru\n");
    xnotice("Source IP and Port: ($si:$sp)\n Route-URI: $route_uri\n");
    xnotice("Received IP and Port: ($Ri:$Rp)\n");
    xnotice("Contact header: $ct\n");
	if (is_present_hf("C-Params")) {
		remove_hf("Contact");
		remove_hf("C-Params");	
		append_hf("Contact: $ct;$hdr(C-Params)\r\n");
	}
#!ifdef WITH_IPSEC
	ipsec_forward("location", IPSEC_FORWARD_FLAGS);
#!endif
	# In case of 1xx and 2xx do NAT
	if(status=~"[12][0-9][0-9]")
		route(NATMANAGE);
#!ifdef WITH_RX
        if (t_check_status("183|200") && has_body("application/sdp")){
		xlog("L_DBG", "IMS: Received 183/200 inside orig_initial_reply\n");

		if (t_is_retr_async_reply()) {
	                xlog("L_DBG", "Dropping retransmitted reply which is still currently suspended\n");
                	drop();
	        }

		xlog("L_DBG", "Diameter: Orig authorizing media via Rx\n");
		$avp(FTAG_CUSTOM_AVP)=$ft;
		$avp(TTAG_CUSTOM_AVP)=$tt;
		$avp(CALLID_CUSTOM_AVP)=$ci;

        if (Rx_AAR("MO_aar_reply","orig","",-1) == 0) {
            exit;
        }
	}
}

route[MO_aar_reply]
{
        #this is async so to know status we have to check the reply avp
	switch ($avp(s:aar_return_code)) {
		case 1:
			xlog("L_DBG", "Diameter: Orig AAR success on media authorization\n");
			break;
		default:
			xlog("L_ERR", "IMS: AAR failed Orig\n");
               		xlog("L_ERR", "IMS: ttag: "+ "$avp(TTAG_CUSTOM_AVP)");
	                xlog("L_ERR", "IMS: ftag: "+ "$avp(FTAG_CUSTOM_AVP)");
	                xlog("L_ERR", "IMS: callid: "+ "$avp(CALLID_CUSTOM_AVP)");
			#comment this if you want to allow even if Rx fails
	                if(dlg_get("$avp(CALLID_CUSTOM_AVP)", "$avp(FTAG_CUSTOM_AVP)", "$avp(TTAG_CUSTOM_AVP)")){
                        	dlg_terminate("all", "Sorry no QoS available");
                       		exit;
               		}
	}
#!endif
}


######################################################################
# In-Dialog-Mo-Requests
######################################################################
route[MO_indialog] {
	xnotice("PCSCF MO_indialog: \n Destination URI: $du\n Request URI: $ru\n");
    xnotice("Source IP and Port: ($si:$sp)\n Route-URI: $route_uri\n");
    xnotice("Received IP and Port: ($Ri:$Rp)\n");
    xnotice("Contact header: $ct\n");
	setflag(FLT_MOBILE_ORIG);
	t_on_reply("MO_indialog_reply");

	# Append rport only if its a request coming from UE
	if (is_request() && ($hdrc(Via) == 1)) {
		force_rport();
	}

#!ifdef WITH_IPSEC
	if ($dd != "" && $rd != "" && $fs != "") {
        if ($rd =~ ".*" + $dd + ".*") {
			ipsec_forward("location", IPSEC_FORWARD_FLAGS);
		}
	}
#!endif
}

onreply_route[MO_indialog_reply] {
	xnotice("PCSCF MO_indialog_reply: \n Destination URI: $du\n Request URI: $ru\n");
    xnotice("Source IP and Port: ($si:$sp)\n Route-URI: $route_uri\n");
    xnotice("Received IP and Port: ($Ri:$Rp)\n");
    xnotice("Contact header: $ct\n");

	# In case of 1xx and 2xx do NAT
	if(status=~"[12][0-9][0-9]")
		route(NATMANAGE);

#!ifdef WITH_RX
	if (t_check_status("183|200") && has_body("application/sdp") && !is_method("PRACK")) {
		if (t_is_retr_async_reply()) {
	                xlog("L_DBG", "Dropping retransmitted reply which is still currently suspended\n");
       	         	drop();
        	}

      		xlog("L_DBG", "IMS: ORIG_SUBSEQUENT reply. This is a 200 OK to a re-INVITE\n");
		xlog("L_DBG", "Diameter: Orig authorizing media via Rx\n");
		$avp(FTAG_CUSTOM_AVP)=$ft;
		$avp(TTAG_CUSTOM_AVP)=$tt;
		$avp(CALLID_CUSTOM_AVP)=$ci;

		if (Rx_AAR("MO_indialog_aar_reply","orig","",-1) == 0) {
            exit;
                }
	}
}

route[MO_indialog_aar_reply]
{
        #this is async so to know status we have to check the reply avp
	switch ($avp(s:aar_return_code)) {
                case 1:
                        xlog("L_DBG", "Diameter: Orig AAR success on media authorization\n"); 
                        break;
                default:
                        xlog("L_ERR", "IMS: AAR failed Orig\n");
                        xlog("L_ERR", "IMS: ttag: "+ "$avp(TTAG_CUSTOM_AVP)");
                        xlog("L_ERR", "IMS: ftag: "+ "$avp(FTAG_CUSTOM_AVP)");
                        xlog("L_ERR", "IMS: callid: "+ "$avp(CALLID_CUSTOM_AVP)");
			#comment this if you want to allow even if Rx fails
                        if(dlg_get("$avp(CALLID_CUSTOM_AVP)", "$avp(FTAG_CUSTOM_AVP)", "$avp(TTAG_CUSTOM_AVP)")){
                                dlg_terminate("all", "Sorry no QoS available");
                                exit;
                        }
        }
#!endif
}
