/* Component implementing a IMS server towards Asterisk's IMS UE
 * (C) 2024 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
 * Author: Pau Espin Pedrol <pespin@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
 */
module IMS_ConnectionHandler {

import from TCCEncoding_Functions all;
import from TCCOpenSecurity_Functions all;
import from General_Types all;
import from Osmocom_Types all;
import from Native_Functions all;
import from Misc_Helpers all;

/* the PIPE asp port allows us to interact with ip xfrm via stdin/stdout */
import from PIPEasp_PortType all;
import from PIPEasp_Types all;
import from PIPEasp_Templates all;

import from SDP_Types all;
import from SDP_Templates all;

import from SIP_Emulation all;
import from SIPmsg_Types all;
import from SIP_Templates all;


modulepar {
	charstring mp_ipsec_setup_script_path := "./IMS_ipsec_setup.sh";
}

const char c_sip_server_name := "osmo-ttcn3-hacks/0.23";


type port IMSCoord_PT message
{
	inout charstring;
} with { extension "internal" };

const charstring IMS_COORD_CMD_REGISTERED := "COORD_CMD_REGISTERED";

type component IMS_ConnHdlr extends SIP_ConnHdlr {
	var charstring g_name;
	var IMS_ConnHdlrPars g_pars;
	timer g_Tguard;
	var PDU_SIP_Request g_rx_sip_req;
	var PDU_SIP_Response g_rx_sip_resp;

	port IMSCoord_PT COORD;
	port PIPEasp_PT PIPE;
}
type record of IMS_ConnHdlr IMS_ConnHdlrList;

type record IMS_AuthVector {
	OCT16 rand,
	OCT16 autn,
	OCT8 res,
	OCT16 ck,
	OCT16 ik
}

type record IMS_ConnHdlrSubscrPars {
	charstring remote_sip_host optional,
	uint16_t remote_sip_port optional,
	charstring imsi,
	charstring display_name,
	charstring password,
	charstring msisdn,
	/* Expected User-Location-Info in P-Access-Network-Info */
	charstring uli_str,
	IMS_AuthVector auth,
	charstring ipsec_auth_key,
	integer ipsec_local_spi_c,
	integer ipsec_local_spi_s,
	integer ipsec_remote_spi_c optional,
	integer ipsec_remote_spi_s optional,
	uint16_t ipsec_remote_port_c optional,
	uint16_t ipsec_remote_port_s optional,
	SipAddr registrar_sip_record,
	CallidString registrar_sip_call_id,
	integer registrar_sip_seq_nr,
	SipUrl local_sip_url_ext,
	SipAddr local_sip_record,
	Contact local_contact,
	P_Associated_Uri p_associated_uri,
	IMS_CallPars cp optional
}
type record of IMS_ConnHdlrSubscrPars IMS_ConnHdlrSubscrParsList;


type record IMS_ConnHdlrPars {
	float t_guard,
	charstring realm,
	charstring local_sip_host,
	uint16_t local_sip_port,
	SipUrl registrar_sip_req_uri,
	Via local_via,
	IMS_ConnHdlrSubscrPars subscr optional
}
type record of IMS_ConnHdlrPars IMS_ConnHdlrParsList;

type record IMS_CallParsMT {
	/* Whether to wait for COORD.receive(COORD_CMD_PICKUP) before accepting the call. */
	boolean wait_coord_cmd_pickup,
	/* Whether to expect CANCEL instead of ACK as answer to our OK */
	boolean exp_cancel
}
template (value) IMS_CallParsMT t_IMS_CallParsMT := {
	wait_coord_cmd_pickup := false,
	exp_cancel := false
}

type record IMS_CallPars {
	SipAddr calling optional,
	SipAddr called optional,

	From from_addr optional,
	To to_addr optional,

	CallidString sip_call_id,
	integer sip_seq_nr,
	charstring sip_body optional,

	charstring local_rtp_addr,
	uint16_t local_rtp_port,

	SDP_Message peer_sdp optional,
	IMS_CallParsMT mt
}

template (value) IMS_CallPars t_IMS_CallPars(charstring local_rtp_addr,
					     uint16_t local_rtp_port := 0,
					     template (omit) SipAddr calling := omit,
					     template (omit) SipAddr called := omit) := {
	calling := calling,
	called := called,
	from_addr := omit,
	to_addr := omit,
	sip_call_id := hex2str(f_rnd_hexstring(15)),
	sip_seq_nr := f_sip_rand_seq_nr(),
	sip_body := omit,
	local_rtp_addr := local_rtp_addr,
	local_rtp_port := local_rtp_port,
	peer_sdp := omit,
	mt := t_IMS_CallParsMT
}

template (value) IMS_ConnHdlrSubscrPars t_IMS_SubscrPars(charstring local_sip_host,
						   uint16_t local_sip_port,
						   charstring domain,
						   charstring imsi,
						   charstring msisdn := "90828",
						   charstring display_name := "Anonymous",
						   charstring password := "secret",
						   template (omit) IMS_CallPars cp := omit) := {
	remote_sip_host := omit,
	remote_sip_port := omit,
	imsi := imsi,
	display_name := f_sip_str_quote(display_name),
	password := password,
	msisdn := msisdn,
	uli_str := "2380100010000101",
	auth := {
		/* The Nonce field is the Base64 encoded version of the RAND value and concatenated with the AUTN: */
		rand := 'd5d5de2bce418d7865ed7fa6956618a2'O,
		autn := 'd42e61db5f15800067393a5b7691a227'O,
		res := '6f2556bbe4366ab1'O,
		ck := '0b389d08c833991734936bec55cac800'O,
		ik := '17141862125bd30c81c4224391a0909a'O
	},
	ipsec_auth_key := "0x17141862125bd30c81c4224391a0909a00000000",
	ipsec_local_spi_c := 4142,
	ipsec_local_spi_s := 4143,
	ipsec_remote_spi_c := omit,
	ipsec_remote_spi_s := omit,
	ipsec_remote_port_c := omit,
	ipsec_remote_port_s := omit,
	registrar_sip_record := ts_SipAddr(ts_HostPort(domain),
					   ts_UserInfo(imsi),
					   f_sip_str_quote(display_name)),
	registrar_sip_call_id := hex2str(f_rnd_hexstring(15)) & "@" & domain,
	registrar_sip_seq_nr := f_sip_rand_seq_nr(),
	local_sip_url_ext := ts_SipUrl(ts_HostPort(domain, local_sip_port),
				       ts_UserInfo(imsi)),
	local_sip_record := ts_SipAddr(ts_HostPort(domain),
				       ts_UserInfo(imsi)),
	local_contact := valueof(ts_Contact({
					ts_ContactAddress(
						ts_Addr_Union_SipUrl(ts_SipUrl(ts_HostPort(
										 domain,
										 local_sip_port),
								     ts_UserInfo(imsi))),
						omit)
				})),
	p_associated_uri := ts_P_Associated_Uri({}),
	cp := cp
}

template (value) IMS_ConnHdlrPars t_IMS_Pars(charstring local_sip_host,
					uint16_t local_sip_port,
					charstring domain,
					charstring imsi,
					template (omit) IMS_CallPars cp := omit) := {
	t_guard := 30.0,
	realm := domain,
	local_sip_host := local_sip_host,
	local_sip_port := local_sip_port,
	registrar_sip_req_uri := valueof(ts_SipUrlHost(domain)),
	local_via := ts_Via_from(ts_HostPort(local_sip_host, local_sip_port)),
	subscr := t_IMS_SubscrPars(local_sip_host, local_sip_port, domain := domain, imsi := imsi, cp := cp)
}

private altstep as_Tguard() runs on IMS_ConnHdlr {
	[] g_Tguard.timeout {
		setverdict(fail, "Tguard timeout");
		mtc.stop;
	}
}

type function ims_void_fn(charstring id) runs on IMS_ConnHdlr;
function f_ims_handler_init(ims_void_fn fn, charstring id, IMS_ConnHdlrPars pars)
runs on IMS_ConnHdlr {
	g_name := id;
	g_pars := pars;
	g_Tguard.start(pars.t_guard);
	activate(as_Tguard());

	/* call the user-supied test case function */
	fn.apply(id);
}

private altstep as_SIP_fail_req(charstring exp_msg_str := "") runs on IMS_ConnHdlr
{
	var PDU_SIP_Request sip_req;
	[] SIP.receive(PDU_SIP_Request:?) -> value sip_req {
		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
					log2str(g_name & ": Received unexpected SIP Req message := ", sip_req, "\nvs exp := ", exp_msg_str));
	}
}

private altstep as_SIP_fail_resp(charstring exp_msg_str := "") runs on IMS_ConnHdlr
{
	var PDU_SIP_Response sip_resp;
	[] SIP.receive(PDU_SIP_Response:?) -> value sip_resp {
		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
					log2str(g_name & ": Received unexpected SIP Resp message := ", sip_resp, "\nvs exp := ", exp_msg_str));
	}
}

private function f_nonce_from_rand_autn(octetstring rand, octetstring autn) return charstring {
	var octetstring concat := rand & autn;
	var charstring nonce := enc_MIME_Base64(concat);
	log("rand=", rand, " & autn=",autn, " => nonce=", nonce);
	return nonce;
}

/* HTTP Digest Authentication Using AKA (AKAv1-MD5): RFC 3310 */
function f_tr_Authorization_AKAv1MD5(WwwAuthenticate www_authenticate,
				     charstring username,
				     charstring uri)
return template (present) Authorization {
	var CommaParam_List digestCln;
	var template (present) Authorization authorization;
	var template (present) Credentials cred;
	var template (omit) GenericParam rx_param;

	digestCln := www_authenticate.challenge[0].digestCln;

	var charstring algorithm := f_sip_param_get_value_present_or_fail(digestCln, "algorithm");
	var charstring realm := f_sip_param_get_value_present_or_fail(digestCln, "realm");
	var charstring nonce := f_sip_param_get_value_present_or_fail(digestCln, "nonce");

	var template (present) CommaParam_List digestResponse := superset(
		tr_Param("username", f_sip_str_quote(username)),
		tr_Param("realm", f_sip_str_quote(realm)),
		tr_Param("nonce", f_sip_str_quote(nonce)),
		tr_Param("uri", f_sip_str_quote(uri)),
		tr_Param("response", ?),
		tr_Param("algorithm", algorithm),
		tr_Param("qop", "auth"),
		tr_Param("cnonce", ?),
		tr_Param("nc", ?)
	);
	cred := tr_Credentials_DigestResponse(digestResponse);
	authorization := tr_Authorization(cred);
	return authorization;
}

private function f_ims_validate_Authorization_AKAv1MD5_Response(Authorization authorization, charstring method)
runs on IMS_ConnHdlr {
	f_sip_digest_validate_Authorization_AKAv1MD5(authorization, method, g_pars.subscr.auth.res);
}


private function f_ims_validate_register_contact(Contact rx_contact)
{
/* IMS contact shows up like this:
 * Contact: <sip:8adf9f3d-9342-4060-aa4f-a909f37fd6f6@192.168.101.2:5060>;+g.3gpp.accesstype="cellular2";video;audio;+g.3gpp.smsip;+g.3gpp.nw-init-ussi;+g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel";+sip.instance="<urn:gsma:imei:35589811-338445-0>"
 */
 /* TODO: "that the UE must include the IMS Communication Service Identifier (ICSI)
in the contact: header to indicate IMS Multimedia Telephony." */
 /* TODO: "The UE must include an IMEI URN in the +sip.instance header field
parameter of the contact: header." */
 /* TODO: "If the UE supports SMS over IP, it must include the feature tag
“+g.3gpp.smsip” in the contact: header." */
 /* TODO: "If the UE supports conversational audio and video service, then this must
be indicated by adding a “video” media feature tag to the contact: header." */
}

/* Validate P-Access-Network-Info: RFC7315 6.4 */
private function f_ims_validate_register_P_Access_Network_info(PDU_SIP_Request req,
							       boolean exp_present := true) runs on IMS_ConnHdlr

{
	if (not exp_present) {
		if (ispresent(g_rx_sip_req.msgHeader.p_access_network_info)) {
			Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
						log2str(g_name & ": Received unexpected [rfc7315 6.4] P-Access-Info := ",
						g_rx_sip_req.msgHeader.p_access_network_info));
		}
		return;
	}

	/* exp_present: */
	var template (present) P_Access_Network_Info expl_tmpl :=
		tr_P_Access_Network_Info({ tr_Access_net_spec_EUTRAN(g_pars.subscr.uli_str) });

	if (not ispresent(g_rx_sip_req.msgHeader.p_access_network_info)) {
		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
					log2str(g_name & ": Received no P-Access-Info vs exp := ",
					expl_tmpl));
	}
	if (not match(g_rx_sip_req.msgHeader.p_access_network_info, expl_tmpl)) {
				Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
							log2str(g_name & ": Received unexpected P-Access-Info := ",
							g_rx_sip_req.msgHeader.p_access_network_info,
							"\nvs exp := ", expl_tmpl));
	}
}

private function f_ims_parse_security_client(Security_client security_client) runs on IMS_ConnHdlr
{
	var boolean found := false;
	for (var integer i := 0; i < lengthof(security_client.sec_mechanism_list); i := i + 1) {
		var Security_mechanism sec_mec := security_client.sec_mechanism_list[i];
		if (sec_mec.mechanism_name != "ipsec-3gpp") {
			log("Skipping Security Mechansim: ", sec_mec.mechanism_name);
			continue;
		}
		var SemicolonParam_List sec_pars := sec_mec.mechanism_params;
		var charstring par_val;
		par_val := f_sip_param_get_value_present_or_fail(sec_pars, "alg");
		if (par_val != "hmac-sha-1-96") {
			log("Skipping Security Mechansim Algo: ", par_val);
			continue;
		}
		par_val := f_sip_param_get_value_present_or_fail(sec_pars, "spi-c");
		g_pars.subscr.ipsec_remote_spi_c := str2int(par_val);
		par_val := f_sip_param_get_value_present_or_fail(sec_pars, "spi-s");
		g_pars.subscr.ipsec_remote_spi_s := str2int(par_val);
		par_val := f_sip_param_get_value_present_or_fail(sec_pars, "port-c");
		g_pars.subscr.ipsec_remote_port_c := str2int(par_val);
		par_val := f_sip_param_get_value_present_or_fail(sec_pars, "port-s");
		g_pars.subscr.ipsec_remote_port_s := str2int(par_val);
		found := true;
		break;
	}

	if (not found) {
		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
					log2str(g_name & "alg=hmac-sha-1-96 not found: ", security_client));
	}

	log("ipsec: remote_spi_c=", g_pars.subscr.ipsec_remote_spi_c, " remote_spi_s=", g_pars.subscr.ipsec_remote_spi_s,
	    "local_spi_c=", g_pars.subscr.ipsec_local_spi_c, " local_spi_s=", g_pars.subscr.ipsec_local_spi_s);
}

private function f_IMS_exec_sync(charstring cmdline, template (present) integer rc := 0)
		runs on IMS_ConnHdlr return ASP_PResult {
	var ASP_PResult res;

	map(self:PIPE, system:PIPE);
	res := f_PIPEasp_exec_sync_PResult(PIPE, cmdline, tr_PResult(?, ?, rc));
	unmap(self:PIPE, system:PIPE);

	return res;
}

private function f_ims_setup_ipsec() runs on IMS_ConnHdlr
{
	var ASP_PResult res;

	var charstring cmd := mp_ipsec_setup_script_path & " " &
		g_pars.local_sip_host & " " &
		int2str(g_pars.local_sip_port) & " " & int2str(g_pars.subscr.ipsec_local_spi_c) & " " &
		int2str(g_pars.local_sip_port) & " " & int2str(g_pars.subscr.ipsec_local_spi_s) & " " &
		g_pars.subscr.remote_sip_host & " " &
		int2str(g_pars.subscr.ipsec_remote_port_c) & " " & int2str(g_pars.subscr.ipsec_remote_spi_c) & " " &
		int2str(g_pars.subscr.ipsec_remote_port_s) & " " & int2str(g_pars.subscr.ipsec_remote_spi_s) & " " &
		g_pars.subscr.ipsec_auth_key;

	res := f_IMS_exec_sync(cmd);

	/* Debug applied rules: */
	/*
	res := f_IMS_exec_sync("ip xfrm state");
	log("ip-xfrm-state Result-Stdout: " & res.stdout);

	res := f_IMS_exec_sync("ip xfrm policy");
	log("ip-xfrm-policy Result-Stdout: " & res.stdout);
	*/
}

private function f_tr_Via_response(Via via_req) return template (present) Via {
	template (present) SemicolonParam_List via_resp_params := ?;

	/*via_resp_params := {
		{ id := "rport", paramValue := int2str(g_pars.subscr.remote_sip_port.subscr.remote_sip_port) },
		{ id := "received", paramValue := g_pars.subscr.remote_sip_host }
	}; */
	return 	tr_Via_from(via_req.viaBody[0].sentBy,
			    via_req.viaBody[0].sentProtocol.transport,
			    via_resp_params);
}

private function f_tr_From(template (value) SipAddr from_req) return template (present) SipAddr {
	return tr_SipAddr_from_val(from_req);
}

private altstep as_SIP_expect_req(template (present) PDU_SIP_Request sip_expect, boolean fail_others := true) runs on IMS_ConnHdlr
{
	var charstring sip_expect_str := log2str(sip_expect);
	[] SIP.receive(sip_expect) -> value g_rx_sip_req;
	[fail_others] as_SIP_fail_req(sip_expect_str);
	[fail_others] as_SIP_fail_resp(sip_expect_str);
}

private function f_gen_sdp() runs on IMS_ConnHdlr return charstring {
	var charstring sdp :=
		"v=0\r\n" &
		"o=0502 2390 1824 IN IP4 " & g_pars.subscr.cp.local_rtp_addr & "\r\n" &
		"s=Talk\r\n" &
		"c=IN IP4 " & g_pars.subscr.cp.local_rtp_addr & "\r\n" &
		"t=0 0\r\n" &
		"a=rtcp-xr:rcvr-rtt=all:10000 stat-summary=loss,dup,jitt,TTL voip-metrics\r\n" &
		"a=record:off\r\n" &
		"m=audio " & int2str(g_pars.subscr.cp.local_rtp_port) & " RTP/AVP 8 96 97 98 0 18 99 100 101\r\n" &
		"a=rtpmap:8 PCMA/8000\r\n" &
		"a=rtpmap:96 opus/48000/2\r\n" &
		"a=fmtp:96 useinbandfec=1\r\n" &
		"a=rtpmap:97 speex/16000\r\n" &
		"a=fmtp:97 vbr=on\r\n" &
		"a=rtpmap:98 speex/8000\r\n" &
		"a=fmtp:98 vbr=on\r\n" &
		"a=fmtp:18 annexb=yes\r\n" &
		"a=rtpmap:99 telephone-event/48000\r\n" &
		"a=rtpmap:100 telephone-event/16000\r\n" &
		"a=rtpmap:101 telephone-event/8000\r\n" &
		"a=rtcp:" & int2str(g_pars.subscr.cp.local_rtp_port + 1) & "\r\n" &
		"a=rtcp-fb:* trr-int 1000\r\n" &
		"a=rtcp-fb:* ccm tmmbr\r\n";
	return sdp;
}

/* Peer is issuing 1st register, accept it: */
altstep as_IMS_register(boolean fail_others := true) runs on IMS_ConnHdlr
{
	var template (present) PDU_SIP_Request exp_req :=
		tr_SIP_REGISTER(g_pars.registrar_sip_req_uri,
				?,
				tr_From(),
				tr_To(),
				tr_Via_from(?),
				require := tr_Require(superset("sec-agree")),
				security_client := tr_Security_client(superset(tr_Security_mechanism("ipsec-3gpp",
												     superset(tr_Param("alg","hmac-sha-1-96"))))),
				supported := tr_Supported(superset("path", "sec-agree")));
	var charstring sip_expect_str := log2str(exp_req);

	[] SIP.receive(exp_req) -> value g_rx_sip_req {
		var template (value) PDU_SIP_Response tx_resp;
		var Via via;
		var CallidString sip_call_id;
		var Contact contact;
		var template (value) From from_addr;
		var template (value) To to_addr;
		var template (value) CommaParam_List digestCln ;
		var template (value) WwwAuthenticate wwwAuthenticate;
		var template (value) Security_server security_server;
		var template (value) Server server_name := ts_Server({c_sip_server_name});
		var template (value) Require require := ts_Require({"sec-agree"});
		var template (value) Supported supported := ts_Supported({"sec-agree"});
		var template (present) Authorization authorization;
		var integer sip_seq_nr;
		var charstring tx_sdp;

		sip_call_id := g_rx_sip_req.msgHeader.callId.callid;
		via := g_rx_sip_req.msgHeader.via;
		via.viaBody[0].viaParams := f_sip_param_set(via.viaBody[0].viaParams, "rport", "1234"); /* TODO: set remote src port of the REGISTER */
		from_addr := g_rx_sip_req.msgHeader.fromField;
		to_addr := g_rx_sip_req.msgHeader.toField;
		sip_seq_nr := g_rx_sip_req.msgHeader.cSeq.seqNumber;

		contact := g_rx_sip_req.msgHeader.contact;
		f_ims_validate_register_contact(contact);

		/* Validate P-Access-Network-Info: rfc7315 6.4:
		 * "3GPP will use the P-Access-Network-Info header field to
		 * carry relatively sensitive information like the cell ID.  Therefore,
		 * the information MUST NOT be sent outside of the 3GPP domain.""
		 * [...] "the sensitive information carried in the
		 * P-Access-Network-Info header field MUST NOT be sent in any initial
		 * unauthenticated and unprotected requests (e.g., REGISTER)."
		 */
		f_ims_validate_register_P_Access_Network_info(g_rx_sip_req, exp_present := false);

		/* TODO: Validate "Expires" is 600000 */

		/* Tx 100 Tyring */
		tx_resp := ts_SIP_Response_Trying(sip_call_id,
					from_addr,
					to_addr,
					via,
					sip_seq_nr,
					"REGISTER",
					allow := omit,
					server := server_name,
					userAgent := omit);
		SIP.send(tx_resp);

		var HostPort hp := valueof(contact.contactBody.contactAddresses[0].addressField.nameAddr.addrSpec.hostPort);
		g_pars.subscr.remote_sip_host := hp.host;
		if (ispresent(hp.portField)) {
			g_pars.subscr.remote_sip_port := hp.portField;
		} else {
			g_pars.subscr.remote_sip_port := 5060;
		}
		f_ims_parse_security_client(g_rx_sip_req.msgHeader.security_client);
		f_ims_setup_ipsec();

		to_addr.toParams := f_sip_param_set(to_addr.toParams, "tag", f_sip_rand_tag());

		digestCln := {
			ts_Param("realm", f_sip_str_quote(g_pars.realm)),
			ts_Param("qop", f_sip_str_quote("auth")),
			ts_Param("algorithm", "AKAv1-MD5"),
			ts_Param("nonce", f_sip_str_quote(f_nonce_from_rand_autn(g_pars.subscr.auth.rand,
										 g_pars.subscr.auth.autn)))
			/* "opaque not needed in IMS "*/
		};
		wwwAuthenticate := ts_WwwAuthenticate( { ts_Challenge_digestCln(digestCln) } )

		/* Security-Server: ipsec-3gpp;q=0.1;prot=esp;mod=trans;spi-c=4096;spi-s=4097;port-c=5104;port-s=6104;alg=hmac-sha-1-96;ealg=null */
		var template (value) SemicolonParam_List sec_params := {
			ts_Param("q", "0.1"),
			ts_Param("prot", "esp"),
			ts_Param("mod", "trans"),
			ts_Param("spi-c", int2str(g_pars.subscr.ipsec_local_spi_c)),
			ts_Param("spi-s", int2str(g_pars.subscr.ipsec_local_spi_s)),
			ts_Param("port-c", int2str(g_pars.local_sip_port)),
			ts_Param("port-s", int2str(g_pars.local_sip_port)),
			ts_Param("alg", "hmac-sha-1-96"),
			ts_Param("ealg", "null")
		};
		security_server := ts_Security_server({
			ts_Security_mechanism("ipsec-3gpp", sec_params)
		});

		/* Tx 401 Unauthorized */
		tx_resp := ts_SIP_Response_Unauthorized(sip_call_id,
					from_addr,
					to_addr,
					via,
					wwwAuthenticate,
					sip_seq_nr,
					"REGISTER",
					p_associated_uri := g_pars.subscr.p_associated_uri,
					security_server := security_server,
					server := server_name,
					supported := supported,
					userAgent := omit);
		SIP.send(tx_resp);

		/* Now we should receive a new REGISTER over ipsec: */
		authorization := f_tr_Authorization_AKAv1MD5(valueof(wwwAuthenticate),
							     g_pars.subscr.imsi & "@" & g_pars.realm,
							     f_sip_SipUrl_to_str(g_pars.registrar_sip_req_uri));
		exp_req :=
		tr_SIP_REGISTER(g_pars.registrar_sip_req_uri,
				?,
				tr_From(),
				tr_To(),
				tr_Via_from(?),
				authorization := authorization);
		SIP.receive(exp_req) -> value g_rx_sip_req;

		sip_call_id := g_rx_sip_req.msgHeader.callId.callid;
		via := g_rx_sip_req.msgHeader.via;
		from_addr := g_rx_sip_req.msgHeader.fromField;
		to_addr := g_rx_sip_req.msgHeader.toField;
		sip_seq_nr := g_rx_sip_req.msgHeader.cSeq.seqNumber;

		/* Tx 100 Trying */
		tx_resp := ts_SIP_Response_Trying(sip_call_id,
					from_addr,
					to_addr,
					via,
					sip_seq_nr,
					"REGISTER",
					allow := omit,
					server := server_name,
					userAgent := omit);
		SIP.send(tx_resp);

		/* Validate Digest Response: */
		f_ims_validate_Authorization_AKAv1MD5_Response(g_rx_sip_req.msgHeader.authorization, "REGISTER");

		/* Validate P-Access-Network-Info: */
		f_ims_validate_register_P_Access_Network_info(g_rx_sip_req, exp_present := true);

		g_pars.subscr.p_associated_uri := valueof(ts_P_Associated_Uri({
				ts_P_Assoc_uri_spec(ts_NameAddr(ts_SipUrl(ts_HostPort(g_pars.realm),
									  ts_UserInfo(g_pars.subscr.msisdn),
									  scheme := "sip"))),
				ts_P_Assoc_uri_spec(ts_NameAddr(ts_SipUrl(ts_HostPort(g_pars.subscr.msisdn),
									  omit,
									  scheme := "tel"))),
				ts_P_Assoc_uri_spec(g_rx_sip_req.msgHeader.toField.addressField.nameAddr)
			}));

		/* Tx 200 OK */
		to_addr.toParams := f_sip_param_set(to_addr.toParams, "tag", f_sip_rand_tag());
		tx_resp := ts_SIP_Response(sip_call_id,
			from_addr,
			to_addr,
			"REGISTER", 200,
			sip_seq_nr,
			"OK",
			via,
			p_associated_uri := g_pars.subscr.p_associated_uri,
			require := require,
			server := server_name,
			supported := supported,
			userAgent := omit);
		SIP.send(tx_resp);
	}
	[fail_others] as_SIP_fail_resp(sip_expect_str);
	[fail_others] as_SIP_fail_req(sip_expect_str);

}

/* Peer wants to unregister, accept it: */
altstep as_IMS_unregister(boolean fail_others := true) runs on IMS_ConnHdlr
{
	var template (present) PDU_SIP_Request exp_req :=
		tr_SIP_REGISTER(g_pars.registrar_sip_req_uri,
				?,
				tr_From(),
				tr_To(),
				tr_Via_from(?),
				expires := tr_Expires(int2str(0)),
				require := tr_Require(superset("sec-agree")),
				security_client := tr_Security_client(superset(tr_Security_mechanism("ipsec-3gpp",
												     superset(tr_Param("alg","hmac-sha-1-96"))))),
				supported := tr_Supported(superset("path", "sec-agree")));
	var charstring sip_expect_str := log2str(exp_req);

	[] SIP.receive(exp_req) -> value g_rx_sip_req {
		var template (value) PDU_SIP_Response tx_resp;
		var Via via;
		var CallidString sip_call_id;
		var Contact contact;
		var template (value) From from_addr;
		var template (value) To to_addr;
		var template (value) CommaParam_List digestCln ;
		var template (value) WwwAuthenticate wwwAuthenticate;
		var template (value) Security_server security_server;
		var template (value) Server server_name := ts_Server({c_sip_server_name});
		var template (value) Require require := ts_Require({"sec-agree"});
		var template (value) Supported supported := ts_Supported({"sec-agree"});
		var template (present) Authorization authorization;
		var integer sip_seq_nr;
		var charstring tx_sdp;

		sip_call_id := g_rx_sip_req.msgHeader.callId.callid;
		via := g_rx_sip_req.msgHeader.via;
		via.viaBody[0].viaParams := f_sip_param_set(via.viaBody[0].viaParams, "rport", "1234"); /* TODO: set remote src port of the REGISTER */
		from_addr := g_rx_sip_req.msgHeader.fromField;
		to_addr := g_rx_sip_req.msgHeader.toField;
		sip_seq_nr := g_rx_sip_req.msgHeader.cSeq.seqNumber;

		contact := g_rx_sip_req.msgHeader.contact;
		f_ims_validate_register_contact(contact);

		/* Validate P-Access-Network-Info: */
		f_ims_validate_register_P_Access_Network_info(g_rx_sip_req, exp_present := true);

		/* Tx 100 Tyring */
		tx_resp := ts_SIP_Response_Trying(sip_call_id,
					from_addr,
					to_addr,
					via,
					sip_seq_nr,
					"REGISTER",
					allow := omit,
					server := server_name,
					userAgent := omit);
		SIP.send(tx_resp);

		/* Change all Contact parameters to expires=0: */
		for (var integer i := 0; i < lengthof(contact.contactBody.contactAddresses); i := i + 1) {
			contact.contactBody.contactAddresses[i].contactParams := valueof({ ts_Param("expires", "0") });
		}
		/* Tx 200 OK */
		to_addr.toParams := f_sip_param_set(to_addr.toParams, "tag", f_sip_rand_tag());
		tx_resp := ts_SIP_Response(sip_call_id,
			from_addr,
			to_addr,
			"REGISTER", 200,
			sip_seq_nr,
			"OK",
			via,
			contact := contact,
			p_associated_uri := g_pars.subscr.p_associated_uri,
			require := require,
			server := server_name,
			supported := supported,
			userAgent := omit);
		SIP.send(tx_resp);
	}
	[fail_others] as_SIP_fail_resp(sip_expect_str);
	[fail_others] as_SIP_fail_req(sip_expect_str);
}

private function f_ConnHdlr_parse_initial_SIP_INVITE(PDU_SIP_Request rx_sip_req) runs on IMS_ConnHdlr
{
	f_SDP_decodeMessage(rx_sip_req.messageBody, g_pars.subscr.cp.peer_sdp);
	log("Rx Initial MO INVITE decoded SDP: ", g_pars.subscr.cp.peer_sdp);

	/* Obtain params: */
	g_pars.subscr.cp.sip_call_id := rx_sip_req.msgHeader.callId.callid;
	g_pars.subscr.cp.from_addr := rx_sip_req.msgHeader.fromField;
	g_pars.subscr.cp.to_addr := rx_sip_req.msgHeader.toField;
	g_pars.subscr.cp.to_addr.toParams := f_sip_param_set(g_pars.subscr.cp.to_addr.toParams, "tag", f_sip_rand_tag());
	g_pars.subscr.cp.sip_seq_nr := rx_sip_req.msgHeader.cSeq.seqNumber;
}

/* Peer is calling us, accept it: */
altstep as_IMS_mo_call_accept(boolean exp_update_to_direct_rtp := false,
			      boolean fail_others := true) runs on IMS_ConnHdlr
{
	var template (present) PDU_SIP_Request exp_req :=
		tr_SIP_INVITE(f_tr_SipUrl_opt_defport(ts_SipUrl_from_Addr_Union(g_pars.subscr.cp.called.addr)),
			      ?,
			      tr_From(tr_Addr_Union_from_val(g_pars.subscr.cp.calling.addr), *),
			      tr_To(tr_Addr_Union_from_val(g_pars.subscr.cp.called.addr), *),
			      tr_Via_from(f_tr_HostPort(g_pars.subscr.remote_sip_host, g_pars.subscr.remote_sip_port)),
			      ?, ?);
	var charstring sip_expect_str := log2str(exp_req);

	[] SIP.receive(exp_req) -> value g_rx_sip_req {
		var template (value) PDU_SIP_Response tx_resp;
		var Via via;
		var charstring tx_sdp;

		/* Obtain params: */
		f_ConnHdlr_parse_initial_SIP_INVITE(g_rx_sip_req);
		via := g_rx_sip_req.msgHeader.via;


		/* Tx 180 Ringing */
		tx_resp := ts_SIP_Response_Ringing(g_pars.subscr.cp.sip_call_id,
						   g_pars.subscr.cp.from_addr,
						   g_pars.subscr.cp.to_addr,
						   via,
						   g_pars.subscr.cp.sip_seq_nr);
		SIP.send(tx_resp);

		/* Tx 200 OK */
		tx_sdp := f_gen_sdp();
		tx_resp := ts_SIP_Response(g_pars.subscr.cp.sip_call_id,
					   g_pars.subscr.cp.from_addr,
					   g_pars.subscr.cp.to_addr,
					   "INVITE", 200,
					   g_pars.subscr.cp.sip_seq_nr,
					   "OK",
					   via,
					   body := tx_sdp);
		SIP.send(tx_resp);

		/* Wait for ACK */
		exp_req := tr_SIP_ACK(f_tr_SipUrl_opt_defport(ts_SipUrl_from_Addr_Union(g_pars.subscr.cp.called.addr)),
				      g_pars.subscr.cp.sip_call_id,
				      g_pars.subscr.cp.from_addr,
				      g_pars.subscr.cp.to_addr,
				      f_tr_Via_response(via),
				      g_pars.subscr.cp.sip_seq_nr, *);
		as_SIP_expect_req(exp_req);
	}
	[fail_others] as_SIP_fail_resp(sip_expect_str);
	[fail_others] as_SIP_fail_req(sip_expect_str);

}

/* Call is terminated by peer: */
altstep as_IMS_exp_call_hangup(template (present) integer exp_seq_nr := ?, boolean fail_others := true) runs on IMS_ConnHdlr
{
	var template (present) PDU_SIP_Request exp_req :=
		tr_SIP_BYE(f_tr_SipUrl_opt_defport(ts_SipUrl_from_Addr_Union(g_pars.subscr.cp.called.addr)),
			   g_pars.subscr.cp.sip_call_id,
			   g_pars.subscr.cp.from_addr,
			   g_pars.subscr.cp.to_addr,
			   tr_Via_from(f_tr_HostPort(g_pars.subscr.remote_sip_host, g_pars.subscr.remote_sip_port)),
			   exp_seq_nr);
	var charstring sip_expect_str := log2str(exp_req);

	[] SIP.receive(exp_req) -> value g_rx_sip_req {
		var template (value) PDU_SIP_Response tx_resp;
		var charstring tx_sdp;
		var Via via;

		/* Update parameters: */
		g_pars.subscr.cp.sip_seq_nr := g_rx_sip_req.msgHeader.cSeq.seqNumber;
		/* "branch" has changed: */
		via := g_rx_sip_req.msgHeader.via;

		/* Tx 200 OK */
		tx_sdp := f_gen_sdp();
		tx_resp := ts_SIP_Response(g_pars.subscr.cp.sip_call_id,
					g_pars.subscr.cp.from_addr,
					g_pars.subscr.cp.to_addr,
					"BYE", 200,
					g_pars.subscr.cp.sip_seq_nr,
					"OK",
					via,
					body := tx_sdp);
		SIP.send(tx_resp);
	}
	[fail_others] as_SIP_fail_resp(sip_expect_str);
	[fail_others] as_SIP_fail_req(sip_expect_str);
}

}
