pespin has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/36547?usp=email )


Change subject: asterisk: Introduce test TC_internal_call_momt
......................................................................

asterisk: Introduce test TC_internal_call_momt

Lots of infrastructure added to allow call establishment and hang up
between 2 users connected to Asterisk.

SIP_Tests is updated to accomodate for necessary changes in
SIP_Templates used by Asterisk_Templates.

Change-Id: Ic5827a3e94b06fbc57f6405bf0f0aa6598c5d1fe
Related: SYS#6782
---
M asterisk/Asterisk_Tests.ttcn
M library/SIP_Emulation.ttcn
M library/SIP_Templates.ttcn
M sip/SIP_Tests.ttcn
4 files changed, 728 insertions(+), 114 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks 
refs/changes/47/36547/1

diff --git a/asterisk/Asterisk_Tests.ttcn b/asterisk/Asterisk_Tests.ttcn
index dab9400..910fc79 100644
--- a/asterisk/Asterisk_Tests.ttcn
+++ b/asterisk/Asterisk_Tests.ttcn
@@ -31,46 +31,65 @@
        integer mp_remote_sip_port := 5060;
 }

+type port Coord_PT message
+{
+       inout charstring;
+} with { extension "internal" };
+private const charstring COORD_CMD_REGISTERED := "COORD_CMD_REGISTERED";
+private const charstring COORD_CMD_START := "COORD_CMD_START";
+private const charstring COORD_CMD_CALL_ESTABLISHED := 
"COORD_CMD_CALL_ESTABLISHED";
+private const charstring COORD_CMD_HANGUP := "COORD_CMD_HANGUP";
+
 type component test_CT {
        var SIP_Emulation_CT vc_SIP;
+       port Coord_PT COORD;
 }

 type component ConnHdlr extends SIP_ConnHdlr {
+       var charstring g_name;
        var ConnHdlrPars g_pars;
        timer g_Tguard;
        var PDU_SIP_Request g_rx_sip_req;
        var PDU_SIP_Response g_rx_sip_resp;
+
+       port Coord_PT COORD;
 }

 type record ConnHdlrPars {
        float t_guard,
        charstring user,
+       charstring display_name,
        charstring password,
-       SipUrl registrar_sip_url,
+       SipUrl registrar_sip_req_uri,
        SipAddr registrar_sip_record,
        CallidString registrar_sip_call_id,
-       Via registrar_via,
        integer registrar_sip_seq_nr,
-       SipAddr sip_url_ext,
+       Via local_via,
+       SipUrl local_sip_url_ext,
+       SipAddr local_sip_record,
        Contact local_contact,
        CallPars cp optional
 }

 template (value) ConnHdlrPars t_Pars(charstring user,
-                                    charstring displayname := "\"Anonymous\"",
-                                    charstring password := "secret") := {
+                                    charstring display_name := "Anonymous",
+                                    charstring password := "secret",
+                                    template (value) CallPars cp := 
t_CallPars()) := {
        t_guard := 30.0,
        user := user,
+       display_name := f_sip_str_quote(display_name),
        password := password,
-       registrar_sip_url := valueof(ts_SipUrlHost(mp_remote_sip_host)),
+       registrar_sip_req_uri := valueof(ts_SipUrlHost(mp_remote_sip_host)),
        registrar_sip_record := ts_SipAddr(ts_HostPort(mp_remote_sip_host),
                                           ts_UserInfo(user),
-                                          displayName := displayname),
+                                          f_sip_str_quote(display_name)),
        registrar_sip_call_id := hex2str(f_rnd_hexstring(15)) & "@" & 
mp_local_sip_host,
-       registrar_via := ts_Via_from(ts_HostPort(mp_local_sip_host, 
mp_local_sip_port)),
        registrar_sip_seq_nr := f_sip_rand_seq_nr(),
-       sip_url_ext := ts_SipAddr(ts_HostPort(mp_local_sip_host, 
mp_local_sip_port),
-                                 ts_UserInfo(user)),
+       local_via := ts_Via_from(ts_HostPort(mp_local_sip_host, 
mp_local_sip_port)),
+       local_sip_url_ext := ts_SipUrl(ts_HostPort(mp_local_sip_host, 
mp_local_sip_port),
+                                      ts_UserInfo(user)),
+       local_sip_record := ts_SipAddr(ts_HostPort(mp_local_sip_host),
+                                      ts_UserInfo(user)),
        local_contact := valueof(ts_Contact({
                                        ts_ContactAddress(
                                                
ts_Addr_Union_SipUrl(ts_SipUrl(ts_HostPort(
@@ -79,46 +98,46 @@
                                                                               
ts_UserInfo(user))),
                                                omit)
                                })),
-       cp := omit
+       cp := cp
 }

 function f_init_ConnHdlrPars(integer idx := 1) runs on test_CT return 
ConnHdlrPars {
-       var ConnHdlrPars pars := valueof(t_Pars("0" & int2str(500 + idx)));
-       return pars;
+       var  template (value) CallPars cp := t_CallPars(idx := idx);
+       var template (value) ConnHdlrPars pars := t_Pars("0" & int2str(500 + 
idx),
+                                                        cp := cp);
+       return valueof(pars);
 }

 type record CallPars {
-       boolean is_mo,
-       charstring calling,
-       charstring called,
+       SipAddr calling optional,
+       SipAddr called optional,

-       CallParsComputed comp optional,
+       SipAddr from_addr optional,
+       SipAddr to_addr optional,

-       charstring sip_rtp_addr,
-       uint16_t sip_rtp_port,
-       charstring cn_rtp_addr,
-       uint16_t cn_rtp_port
-}
-
-type record CallParsComputed {
        CallidString sip_call_id,
-       charstring sip_body,
-       integer sip_seq_nr
+       integer sip_seq_nr,
+       charstring sip_body optional,
+
+       charstring local_rtp_addr,
+       uint16_t local_rtp_port,
+
+       SDP_Message peer_sdp optional
 }

-private template (value) CallPars t_CallPars(boolean is_mo) := {
-       is_mo := is_mo,
-       calling := "12345",
-       called := "98766",
-       comp := {
-               sip_call_id := hex2str(f_rnd_hexstring(15)),
-               sip_body := "",
-               sip_seq_nr := f_sip_rand_seq_nr()
-       },
-       sip_rtp_addr := "1.2.3.4",
-       sip_rtp_port := 1234,
-       cn_rtp_addr := "5.6.7.8",
-       cn_rtp_port := 5678
+private template (value) CallPars t_CallPars(integer idx := 1,
+                                            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 := mp_local_sip_host,
+       local_rtp_port := 1234 + 2*idx,
+       peer_sdp := omit
 }

 function f_init() runs on test_CT {
@@ -131,13 +150,15 @@
 function f_start_handler(void_fn fn, ConnHdlrPars pars)
 runs on test_CT return ConnHdlr {
        var ConnHdlr vc_conn;
-       var charstring id := testcasename();
+       var charstring id := testcasename() & "-ConnHdlr-" & pars.user;

-       vc_conn := ConnHdlr.create(id);
+       vc_conn := ConnHdlr.create(id) alive;

        connect(vc_conn:SIP, vc_SIP:CLIENT);
        connect(vc_conn:SIP_PROC, vc_SIP:CLIENT_PROC);

+       connect(vc_conn:COORD, self:COORD);
+
        vc_conn.start(f_handler_init(fn, id, pars));
        return vc_conn;
 }
@@ -151,6 +172,7 @@

 private function f_handler_init(void_fn fn, charstring id, ConnHdlrPars pars)
 runs on ConnHdlr {
+       g_name := id;
        g_pars := pars;
        g_Tguard.start(pars.t_guard);
        activate(as_Tguard());
@@ -163,21 +185,45 @@
        fn.apply(id);
 }

-altstep as_SIP_expect_req(template PDU_SIP_Request sip_expect) runs on ConnHdlr
+private altstep as_SIP_fail_req(charstring exp_msg_str := "") runs on ConnHdlr
 {
-       [] SIP.receive(sip_expect) -> value g_rx_sip_req;
-       [] SIP.receive {
-               log("FAIL: expected SIP message ", sip_expect);
-               Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received 
unexpected SIP message");
+       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));
        }
 }

-altstep as_SIP_expect_resp(template PDU_SIP_Response sip_expect) runs on 
ConnHdlr
+private altstep as_SIP_fail_resp(charstring exp_msg_str := "") runs on 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));
+       }
+}
+
+altstep as_SIP_expect_req(template (present) PDU_SIP_Request sip_expect, 
boolean fail_others := true) runs on 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);
+}
+
+altstep as_SIP_expect_resp(template (present) PDU_SIP_Response sip_expect, 
boolean fail_others := true) runs on ConnHdlr
+{
+       var charstring sip_expect_str := log2str(sip_expect);
        [] SIP.receive(sip_expect) -> value g_rx_sip_resp;
-       [] SIP.receive {
-               log("FAIL: expected SIP message ", sip_expect);
-               Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received 
unexpected SIP message");
+       [fail_others] as_SIP_fail_resp(sip_expect_str);
+       [fail_others] as_SIP_fail_req(sip_expect_str);
+}
+
+altstep as_SIP_ignore_resp(template PDU_SIP_Response sip_expect := ?) runs on 
ConnHdlr
+{
+       [] SIP.receive(sip_expect) -> value g_rx_sip_resp {
+               log("Ignoring ", g_rx_sip_resp);
+               repeat;
        }
 }

@@ -192,15 +238,45 @@
                            via_resp_params);
 }

-private function f_tr_To_response(SipAddr to_req) return template (present) 
SipAddr {
+private function f_tr_To_response(template (value) SipAddr to_req) return 
template (present) SipAddr {
        return tr_SipAddr_from_val(to_req);
 }

-function f_SIP_register() runs on ConnHdlr return PDU_SIP_Response
+private function f_tr_From(template (value) SipAddr from_req) return template 
(present) SipAddr {
+       return tr_SipAddr_from_val(from_req);
+}
+
+private function f_gen_sdp() runs on ConnHdlr return charstring {
+       var charstring sdp :=
+               "v=0\r\n" &
+               "o=0502 2390 1824 IN IP4 " & g_pars.cp.local_rtp_addr & "\r\n" &
+               "s=Talk\r\n" &
+               "c=IN IP4 " & g_pars.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.cp.local_rtp_port) & " RTP/AVP 96 
97 98 0 8 18 99 100 101\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.cp.local_rtp_port + 1) & "\r\n" &
+               "a=rtcp-fb:* trr-int 1000\r\n" &
+               "a=rtcp-fb:* ccm tmmbr\r\n";
+       return sdp;
+}
+
+private function f_SIP_register() runs on ConnHdlr return PDU_SIP_Response
 {
        var template (present) PDU_SIP_Response exp;
        var Authorization authorization;
-       var Via via := g_pars.registrar_via;
+       var Via via := g_pars.local_via;
        var SipAddr from_sipaddr := g_pars.registrar_sip_record;
        var charstring branch_value;

@@ -211,7 +287,7 @@

        via.viaBody[0].viaParams := f_sip_param_set(via.viaBody[0].viaParams, 
"branch", branch_value);
        from_sipaddr.params := f_sip_param_set(from_sipaddr.params, "tag", 
f_sip_rand_tag());
-       SIP.send(ts_SIP_REGISTER(g_pars.registrar_sip_url,
+       SIP.send(ts_SIP_REGISTER(g_pars.registrar_sip_req_uri,
                                 g_pars.registrar_sip_call_id,
                                 from_sipaddr,
                                 g_pars.registrar_sip_record,
@@ -220,7 +296,7 @@
                                 g_pars.local_contact,
                                 ts_Expires("7200")));

-       exp := tr_SIP_Response_REGISTER_Unauthorized(
+       exp := tr_SIP_Response_Unauthorized(
                        g_pars.registrar_sip_call_id,
                        from_sipaddr,
                        f_tr_To_response(g_pars.registrar_sip_record),
@@ -233,7 +309,8 @@
        /* Digest Auth: RFC 2617 */
        authorization := 
f_sip_digest_gen_Authorization(g_rx_sip_resp.msgHeader.wwwAuthenticate,
                                                        g_pars.user, 
g_pars.password,
-                                                       "REGISTER", "sip:" & 
mp_remote_sip_host)
+                                                       "REGISTER",
+                                                       
f_sip_SipUrl_to_str(g_pars.registrar_sip_req_uri))

        /* New transaction: */
        g_pars.registrar_sip_seq_nr := g_pars.registrar_sip_seq_nr + 1;
@@ -243,7 +320,7 @@
                                         g_pars.registrar_sip_seq_nr);
        via.viaBody[0].viaParams := f_sip_param_set(via.viaBody[0].viaParams, 
"branch", branch_value);

-       SIP.send(ts_SIP_REGISTER(g_pars.registrar_sip_url,
+       SIP.send(ts_SIP_REGISTER(g_pars.registrar_sip_req_uri,
                                g_pars.registrar_sip_call_id,
                                from_sipaddr,
                                g_pars.registrar_sip_record,
@@ -269,6 +346,303 @@
        return g_rx_sip_resp;
 }

+private function f_SIP_mo_call_setup() runs on ConnHdlr
+{
+       var template (value) PDU_SIP_Request req;
+       var template (present) PDU_SIP_Response exp;
+       var Via via;
+       var charstring tx_sdp := f_gen_sdp();
+       var default d_trying, d_ringing;
+       var charstring branch_value;
+
+       /* RFC 3261 8.1.1.3 From */
+       g_pars.cp.from_addr := g_pars.cp.calling;
+       g_pars.cp.from_addr.params := 
f_sip_param_set(g_pars.cp.from_addr.params, "tag", f_sip_rand_tag());
+       g_pars.cp.to_addr := g_pars.cp.called;
+       branch_value := 
f_sip_gen_branch(f_sip_SipAddr_to_str(g_pars.cp.from_addr),
+                                        
f_sip_SipAddr_to_str(valueof(g_pars.cp.to_addr)),
+                                        g_pars.cp.sip_call_id,
+                                        g_pars.cp.sip_seq_nr);
+       via := g_pars.local_via;
+       via.viaBody[0].viaParams := f_sip_param_set(via.viaBody[0].viaParams, 
"branch", branch_value);
+
+       req := ts_SIP_INVITE(g_pars.cp.sip_call_id,
+                            g_pars.cp.from_addr,
+                            g_pars.cp.to_addr,
+                            via,
+                            g_pars.local_contact,
+                            g_pars.cp.sip_seq_nr,
+                            body := tx_sdp);
+
+       SIP.send(req);
+
+       /* RFC 3261 22.2: */
+       exp := tr_SIP_Response_Unauthorized(
+                       g_pars.cp.sip_call_id,
+                       f_tr_From(g_pars.cp.from_addr),
+                       f_tr_To_response(g_pars.cp.to_addr),
+                       f_tr_Via_response(via),
+                       *,
+                       tr_WwwAuthenticate({tr_Challenge_digestCln(?)}),
+                       g_pars.cp.sip_seq_nr, "INVITE");
+       as_SIP_expect_resp(exp);
+
+       /* Digest Auth: RFC 2617 */
+       req.msgHeader.authorization := f_sip_digest_gen_Authorization(
+                                               
g_rx_sip_resp.msgHeader.wwwAuthenticate,
+                                               g_pars.user, g_pars.password,
+                                               "INVITE",
+                                               
f_sip_SipUrl_to_str(g_pars.registrar_sip_req_uri))
+       g_pars.cp.sip_seq_nr := g_pars.cp.sip_seq_nr + 1;
+       f_sip_Request_inc_seq_nr(req);
+       SIP.send(req);
+
+       /* Conditionally match and accept 100 Trying. */
+       exp := tr_SIP_Response_Trying(g_pars.cp.sip_call_id,
+                       g_pars.cp.from_addr,
+                       f_tr_To_response(g_pars.cp.to_addr),
+                       f_tr_Via_response(via),
+                       g_pars.cp.sip_seq_nr, "INVITE");
+       d_trying := activate(as_SIP_ignore_resp(exp));
+
+       /* Conditionally match and accept 180 Ringing */
+       exp := tr_SIP_Response_Ringing(g_pars.cp.sip_call_id,
+                       g_pars.cp.from_addr,
+                       f_tr_To_response(g_pars.cp.to_addr),
+                       f_tr_Via_response(via),
+                       g_pars.cp.sip_seq_nr, "INVITE");
+       d_ringing := activate(as_SIP_ignore_resp(exp));
+
+       /* Wait for OK answer */
+       exp := tr_SIP_Response(
+                       g_pars.cp.sip_call_id,
+                       g_pars.cp.from_addr,
+                       f_tr_To_response(g_pars.cp.to_addr),
+                       f_tr_Via_response(via),
+                       *,
+                       "INVITE", 200,
+                       g_pars.cp.sip_seq_nr, "OK",
+                       body := ?);
+       as_SIP_expect_resp(exp, fail_others := false);
+
+       deactivate(d_trying);
+       deactivate(d_ringing);
+
+       /* Update To with the tags received from peer: */
+       g_pars.cp.to_addr := 
valueof(ts_SipAddr_from_Addr_Union(g_rx_sip_resp.msgHeader.toField.addressField,
+                                                               
g_rx_sip_resp.msgHeader.toField.toParams));
+
+       /* Transmit ACK */
+       g_pars.cp.sip_seq_nr := g_pars.cp.sip_seq_nr + 1;
+       req := ts_SIP_ACK(g_pars.cp.sip_call_id,
+                         g_pars.cp.from_addr,
+                         g_pars.cp.to_addr,
+                         via,
+                         g_pars.cp.sip_seq_nr,
+                         omit);
+       SIP.send(req);
+       g_pars.cp.sip_seq_nr := g_pars.cp.sip_seq_nr + 1;
+}
+
+/* Peer is calling us, accept it: */
+private altstep as_SIP_mt_call_accept(boolean exp_update_to_direct_rtp := 
true, boolean fail_others := true) runs on ConnHdlr
+{
+       var template (present) PDU_SIP_Request exp_req :=
+               tr_SIP_INVITE(f_tr_SipUrl_opt_defport(g_pars.local_sip_url_ext),
+                             ?,
+                             f_tr_From(g_pars.cp.calling),
+                             g_pars.cp.called,
+                             tr_Via_from(f_tr_HostPort(mp_remote_sip_host, 
mp_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;
+
+               f_SDP_decodeMessage(g_rx_sip_req.messageBody, 
g_pars.cp.peer_sdp);
+               log("Rx Initial MT INVITE decoded SDP: ", g_pars.cp.peer_sdp);
+
+               /* Obtain params: */
+               g_pars.cp.sip_call_id := g_rx_sip_req.msgHeader.callId.callid;
+               g_pars.cp.from_addr := 
valueof(ts_SipAddr_from_Addr_Union(g_rx_sip_req.msgHeader.fromField.addressField,
+                                                                       
g_rx_sip_req.msgHeader.fromField.fromParams));
+               g_pars.cp.to_addr := 
valueof(ts_SipAddr_from_Addr_Union(g_rx_sip_req.msgHeader.toField.addressField,
+                                                                       
g_rx_sip_req.msgHeader.toField.toParams));
+               g_pars.cp.to_addr.params := 
f_sip_param_set(g_pars.cp.to_addr.params, "tag", f_sip_rand_tag());
+               g_pars.cp.sip_seq_nr := g_rx_sip_req.msgHeader.cSeq.seqNumber;
+               via := g_rx_sip_req.msgHeader.via;
+
+
+               /* Tx 180 Ringing */
+               tx_resp := ts_SIP_Response_Ringing(g_pars.cp.sip_call_id,
+                                               g_pars.cp.from_addr,
+                                               g_pars.cp.to_addr,
+                                               via,
+                                               g_pars.cp.sip_seq_nr);
+               SIP.send(tx_resp);
+
+               /* Tx 200 OK */
+               tx_sdp := f_gen_sdp();
+               tx_resp := ts_SIP_Response(g_pars.cp.sip_call_id,
+                                       g_pars.cp.from_addr,
+                                       g_pars.cp.to_addr,
+                                       "INVITE", 200,
+                                       g_pars.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(g_pars.local_sip_url_ext),
+                               g_pars.cp.sip_call_id,
+                               g_pars.cp.from_addr,
+                               g_pars.cp.to_addr,
+                               f_tr_Via_response(via),
+                               g_pars.cp.sip_seq_nr, *);
+               as_SIP_expect_req(exp_req);
+
+               if (exp_update_to_direct_rtp) {
+                       /* Asterisk will now update the session to connect us 
to MO directly: */
+                       /* Via is not kept since anyway "branch" will change 
upon following INVITE. */
+                       as_SIP_exp_call_update(g_pars.cp.sip_seq_nr + 1);
+               }
+       }
+       [fail_others] as_SIP_fail_resp(sip_expect_str);
+       [fail_others] as_SIP_fail_req(sip_expect_str);
+
+}
+
+/* New INVITE arrives after MT call is established. Accept it: */
+private altstep as_SIP_exp_call_update(template (present) integer exp_seq_nr 
:= ?, boolean fail_others := true) runs on ConnHdlr
+{
+       var template (present) PDU_SIP_Request exp_req :=
+               tr_SIP_INVITE(f_tr_SipUrl_opt_defport(g_pars.local_sip_url_ext),
+                                                     g_pars.cp.sip_call_id,
+                                                     g_pars.cp.from_addr,
+                                                     g_pars.cp.to_addr,
+                                                     
tr_Via_from(f_tr_HostPort(mp_remote_sip_host, mp_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;
+
+               f_SDP_decodeMessage(g_rx_sip_req.messageBody, 
g_pars.cp.peer_sdp);
+               log("Rx Update MT INVITE decoded SDP: ", g_pars.cp.peer_sdp);
+
+               /* Update parameters: */
+               g_pars.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.cp.sip_call_id,
+                                       g_pars.cp.from_addr,
+                                       g_pars.cp.to_addr,
+                                       "INVITE", 200,
+                                       g_pars.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(g_pars.local_sip_url_ext),
+                               g_pars.cp.sip_call_id,
+                               g_pars.cp.from_addr,
+                               g_pars.cp.to_addr,
+                               f_tr_Via_response(via),
+                               g_pars.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);
+}
+
+/* Tx BYE: */
+private function f_SIP_do_call_hangup() runs on ConnHdlr
+{
+       var template (value) PDU_SIP_Request req;
+       var template (present) PDU_SIP_Response exp_resp;
+       var Via via;
+       var charstring branch_value;
+
+       branch_value := 
f_sip_gen_branch(f_sip_SipAddr_to_str(g_pars.cp.from_addr),
+                                        
f_sip_SipAddr_to_str(valueof(g_pars.cp.to_addr)),
+                                        g_pars.cp.sip_call_id,
+                                        g_pars.cp.sip_seq_nr);
+
+       via := g_pars.local_via;
+       via.viaBody[0].viaParams := f_sip_param_set(via.viaBody[0].viaParams, 
"branch", branch_value);
+
+       /* Transmit ACK */
+       req := ts_SIP_BYE(g_pars.cp.sip_call_id,
+                         g_pars.cp.from_addr,
+                         g_pars.cp.to_addr,
+                         via,
+                         g_pars.cp.sip_seq_nr,
+                         omit);
+       SIP.send(req);
+
+       /* Wait for OK answer */
+       exp_resp := tr_SIP_Response(
+                       g_pars.cp.sip_call_id,
+                       g_pars.cp.from_addr,
+                       f_tr_To_response(g_pars.cp.to_addr),
+                       f_tr_Via_response(via),
+                       *,
+                       "BYE", 200,
+                       g_pars.cp.sip_seq_nr, "OK");
+       as_SIP_expect_resp(exp_resp);
+
+       g_pars.cp.sip_seq_nr := g_pars.cp.sip_seq_nr + 1;
+}
+
+/* Call is terminated by peer: */
+private altstep as_SIP_exp_call_hangup(template (present) integer exp_seq_nr 
:= ?, boolean fail_others := true) runs on ConnHdlr
+{
+       var template (present) PDU_SIP_Request exp_req :=
+               tr_SIP_BYE(f_tr_SipUrl_opt_defport(g_pars.local_sip_url_ext),
+                                                  g_pars.cp.sip_call_id,
+                                                  g_pars.cp.from_addr,
+                                                  g_pars.cp.to_addr,
+                                                  
tr_Via_from(f_tr_HostPort(mp_remote_sip_host, mp_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.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.cp.sip_call_id,
+                                       g_pars.cp.from_addr,
+                                       g_pars.cp.to_addr,
+                                       "BYE", 200,
+                                       g_pars.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);
+}
+
 /* Test SIP registration of local clients */
 private function f_TC_internal_registration(charstring id) runs on ConnHdlr {

@@ -276,7 +650,6 @@
        // f_SIP_deregister();
        setverdict(pass);
 }
-
 testcase TC_internal_registration() runs on test_CT {
        var ConnHdlrPars pars;
        var ConnHdlr vc_conn;
@@ -286,6 +659,72 @@
        vc_conn.done;
 }

+/* Successful SIP MO-MT Call between local clients: */
+private function f_TC_internal_call_mo(charstring id) runs on ConnHdlr {
+
+       f_SIP_register();
+       COORD.send(COORD_CMD_REGISTERED);
+
+       COORD.receive(COORD_CMD_START);
+       f_SIP_mo_call_setup();
+       COORD.send(COORD_CMD_CALL_ESTABLISHED);
+
+       COORD.receive(COORD_CMD_HANGUP);
+       f_SIP_do_call_hangup();
+
+       setverdict(pass);
+}
+private function f_TC_internal_call_mt(charstring id) runs on ConnHdlr {
+
+       
f_create_sip_expect(valueof(ts_SipUrl_from_Addr_Union(g_pars.cp.called.addr)));
+
+       f_SIP_register();
+       COORD.send(COORD_CMD_REGISTERED);
+
+       as_SIP_mt_call_accept();
+       COORD.send(COORD_CMD_CALL_ESTABLISHED);
+
+       /* Once MO hangs up, Asterisk updates us to point RTP to it: */
+       as_SIP_exp_call_update(g_pars.cp.sip_seq_nr + 1);
+       as_SIP_exp_call_hangup(g_pars.cp.sip_seq_nr + 1);
+
+       setverdict(pass);
+}
+testcase TC_internal_call_momt() runs on test_CT {
+       var ConnHdlrPars pars[2];
+       var ConnHdlr vc_conn[2];
+       f_init();
+       pars[0] := f_init_ConnHdlrPars(idx := 1);
+       pars[1] := f_init_ConnHdlrPars(idx := 2);
+
+       pars[0].cp.calling := pars[0].registrar_sip_record;
+       pars[0].cp.called := pars[1].registrar_sip_record;
+
+       pars[1].cp.calling := pars[0].registrar_sip_record;
+       pars[1].cp.called := pars[1].local_sip_record;
+
+       vc_conn[0] := f_start_handler(refers(f_TC_internal_call_mo), pars[0]);
+       vc_conn[1] := f_start_handler(refers(f_TC_internal_call_mt), pars[1]);
+
+       interleave {
+       [] COORD.receive(COORD_CMD_REGISTERED) from vc_conn[0];
+       [] COORD.receive(COORD_CMD_REGISTERED) from vc_conn[1];
+       }
+
+       COORD.send(COORD_CMD_START) to vc_conn[0];
+
+       interleave {
+       [] COORD.receive(COORD_CMD_CALL_ESTABLISHED) from vc_conn[0];
+       [] COORD.receive(COORD_CMD_CALL_ESTABLISHED) from vc_conn[1];
+       }
+
+       COORD.send(COORD_CMD_HANGUP) to vc_conn[0];
+
+
+       vc_conn[0].done;
+       vc_conn[1].done;
+}
+
 testcase TC_selftest() runs on test_CT {
        f_sip_digest_selftest();
        setverdict(pass);
@@ -293,6 +732,7 @@

 control {
        execute( TC_internal_registration() );
+       execute( TC_internal_call_momt() );
 }

 }
diff --git a/library/SIP_Emulation.ttcn b/library/SIP_Emulation.ttcn
index 4aef536..559b575 100644
--- a/library/SIP_Emulation.ttcn
+++ b/library/SIP_Emulation.ttcn
@@ -237,7 +237,7 @@
                create_cb := refers(SIP_Emulation.ExpectedCreateCallback)
        };

-       ct := SIP_Emulation_CT.create(id);
+       ct := SIP_Emulation_CT.create(id) alive;
        map(ct:SIP, system:SIP);
        ct.start(SIP_Emulation.main(ops, id));
 }
diff --git a/library/SIP_Templates.ttcn b/library/SIP_Templates.ttcn
index 7de2d27..9a9b44c 100644
--- a/library/SIP_Templates.ttcn
+++ b/library/SIP_Templates.ttcn
@@ -52,8 +52,18 @@
        headers := *
 }

-template (value) SipUrl ts_SipUrlHost(template (value) charstring host)
-       := ts_SipUrl(ts_HostPort(host));
+template (value) SipUrl ts_SipUrlHost(template (value) charstring host,
+                                     template (omit) integer portField := omit)
+       := ts_SipUrl(ts_HostPort(host, portField));
+
+function ts_SipUrl_from_Addr_Union(template (value) Addr_Union au)
+return template (value) SipUrl {
+       if (ischosen(au.nameAddr)) {
+               return au.nameAddr.addrSpec;
+       } else { /* au.addrSpecUnion */
+               return au.addrSpecUnion;
+       }
+}

 template (value) Credentials ts_Credentials_DigestResponse(template (value) 
CommaParam_List digestResponse) := {
        digestResponse := digestResponse
@@ -212,27 +222,74 @@
 }

 /* build a receive template from a value: substitute '*' for omit */
-function tr_SipAddr_from_val(SipAddr tin) return template (present) SipAddr {
+function tr_SipUrl_from_val(template (value) SipUrl tin) return template 
(present) SipUrl {
+       var template (present) SipUrl ret := tin;
+
+       /* if the port number is 5060, it may be omitted */
+       if (ispresent(tin.hostPort.portField) and
+           valueof(tin.hostPort.portField) == 5060) {
+               ret.hostPort.portField := 5060 ifpresent;
+       }
+       if (not ispresent(tin.userInfo.password)) {
+               ret.userInfo.password := *;
+       }
+
+       return ret;
+}
+function tr_SipAddr_from_val(template (value) SipAddr tin) return template 
(present) SipAddr {
        var template (present) SipAddr ret := tin;
-       if (tin.addr.nameAddr.displayName == omit) {
+
+       if (not ispresent(tin.addr.nameAddr.displayName)) {
                ret.addr.nameAddr.displayName := *;
+       } else if 
(f_str_tolower(f_sip_str_unquote(tin.addr.nameAddr.displayName)) == 
"anonymous") {
+               /* if the user is Anonymous, it may be omitted */
+               ret.addr.nameAddr.displayName := tin.addr.nameAddr.displayName 
ifpresent;
        }
-       if (tin.addr.nameAddr.addrSpec.userInfo.password == omit) {
-               ret.addr.nameAddr.addrSpec.userInfo.password := *;
-       }
-       if (tin.params == omit) {
+
+       ret.addr.nameAddr.addrSpec := 
tr_SipUrl_from_val(tin.addr.nameAddr.addrSpec);
+
+       if (not ispresent(tin.params)) {
                ret.params := *;
        }
        return ret;
 }

+function ts_SipAddr_from_Addr_Union(template (value) Addr_Union au,
+                                   template (omit) SemicolonParam_List params 
:= omit)
+return template (value) SipAddr {
+       var template (value) SipUrl addrSpec := ts_SipUrl_from_Addr_Union(au);
+       var template (omit) charstring displayName;
+
+       if (ischosen(au.nameAddr)) {
+               displayName := au.nameAddr.displayName;
+       } else { /* au.addrSpecUnion */
+               displayName := omit
+       }
+
+       return ts_SipAddr(addrSpec.hostPort,
+                         addrSpec.userInfo,
+                         displayName,
+                         params);
+}
+
 template (value) HostPort ts_HostPort(template (omit) charstring host := omit,
                                      template (omit) integer portField := 
omit) := {
        host := host,
        portField := portField
 }
-function tr_HostPort(template HostPort hp) return template HostPort {
-       var template HostPort hpout := hp;
+
+template (present) HostPort tr_HostPort(template charstring host := *,
+                                       template integer portField := *) := {
+       host := host,
+       portField := portField
+}
+function f_tr_HostPort(template charstring host := *,
+                      template integer portField := *)
+return template (present) HostPort {
+       return f_tr_HostPort_opt_defport(tr_HostPort(host, portField));
+}
+function f_tr_HostPort_opt_defport(template (present) HostPort hp) return 
template (present) HostPort {
+       var template (present) HostPort hpout := hp;
        /* if the port number is 5060, it may be omitted */
        if (isvalue(hp.portField) and valueof(hp.portField) == 5060) {
                hpout.portField := 5060 ifpresent;
@@ -240,6 +297,11 @@
        return hpout;
 }

+function f_tr_SipUrl_opt_defport(template (present) SipUrl url) return 
template (present) SipUrl {
+       var template (present) SipUrl urlout := url;
+       urlout.hostPort := f_tr_HostPort_opt_defport(url.hostPort);
+       return urlout;
+}

 template (value) UserInfo ts_UserInfo(template (value) charstring 
userOrTelephoneSubscriber,
                                      template (omit) charstring password := 
omit) := {
@@ -515,7 +577,7 @@
                template charstring body := *) := {
        requestLine := tr_SIP_ReqLine(REGISTER_E, sip_url_host_port),
        msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
-                                    
tr_Via_from(tr_HostPort(from_addr.addr.nameAddr.addrSpec.hostPort)),
+                                    
tr_Via_from(f_tr_HostPort_opt_defport(from_addr.addr.nameAddr.addrSpec.hostPort)),
                                     "REGISTER", *, seq_nr,
                                     expires := expires),
        messageBody := body,
@@ -523,96 +585,102 @@
 }

 template (value) PDU_SIP_Request
-ts_SIP_INVITE(CallidString call_id,
-             SipAddr from_addr,
-             SipAddr to_addr,
+ts_SIP_INVITE(template (value) CallidString call_id,
+             template (value) SipAddr from_addr,
+             template (value) SipAddr to_addr,
+             template (value) Via via,
+             template (value) Contact contact,
              integer seq_nr,
              template (omit) charstring body := omit) := {
        requestLine := ts_SIP_ReqLine(INVITE_E, to_addr.addr.nameAddr.addrSpec),
-       msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr,
-                                    ts_Contact_SipAddr(from_addr),
+       msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact,
                                     "INVITE", seq_nr,
-                                    
ts_Via_from(from_addr.addr.nameAddr.addrSpec.hostPort),
+                                    via,
                                     f_ContentTypeOrOmit(ts_CT_SDP, body)),
        messageBody := body,
        payload := omit
 }
 template (present) PDU_SIP_Request
-tr_SIP_INVITE(template CallidString call_id,
+tr_SIP_INVITE(template (present) SipUrl uri,
+             template CallidString call_id,
              template SipAddr from_addr,
              template SipAddr to_addr,
+             template Via via := tr_Via_from(f_tr_HostPort_opt_defport(?)),
              template integer seq_nr,
              template charstring body) := {
-       requestLine := tr_SIP_ReqLine(INVITE_E, to_addr.addr.nameAddr.addrSpec),
+       requestLine := tr_SIP_ReqLine(INVITE_E, uri),
        msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, ?,
-                                    
tr_Via_from(tr_HostPort(from_addr.addr.nameAddr.addrSpec.hostPort)),
-                                    "INVITE", *, seq_nr),
+                                    via, "INVITE", *, seq_nr),
        messageBody := body,
        payload := omit
 }

 template (value) PDU_SIP_Request
 ts_SIP_BYE(CallidString call_id,
-          SipAddr from_addr,
-          SipAddr to_addr,
+          template (value) SipAddr from_addr,
+          template (value) SipAddr to_addr,
+          template (value) Via via,
           integer seq_nr,
           template (omit) charstring body) := {
        requestLine := ts_SIP_ReqLine(BYE_E, to_addr.addr.nameAddr.addrSpec),
        msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, "BYE", 
seq_nr,
-                                    
ts_Via_from(from_addr.addr.nameAddr.addrSpec.hostPort),
-                                    f_ContentTypeOrOmit(ts_CT_SDP, body)),
+                                    via, f_ContentTypeOrOmit(ts_CT_SDP, body)),
        messageBody := body,
        payload := omit
 }

 template (present) PDU_SIP_Request
-tr_SIP_BYE(template CallidString call_id,
+tr_SIP_BYE(template (present) SipUrl uri,
+          template CallidString call_id,
           template SipAddr from_addr,
           template SipAddr to_addr,
+          template Via via,
           template integer seq_nr,
-          template charstring body) := {
-       requestLine := tr_SIP_ReqLine(BYE_E, to_addr.addr.nameAddr.addrSpec),
+          template charstring body := *) := {
+       requestLine := tr_SIP_ReqLine(BYE_E, uri),
        msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, omit,
-                                    
tr_Via_from(tr_HostPort(from_addr.addr.nameAddr.addrSpec.hostPort)),
-                                    "BYE", *, seq_nr),
+                                    via, "BYE", *, seq_nr),
        messageBody := body,
        payload := omit
 }


 template (value) PDU_SIP_Request
-ts_SIP_ACK(CallidString call_id,
-          SipAddr from_addr,
-          SipAddr to_addr,
+ts_SIP_ACK(template (value) CallidString call_id,
+          template (value) SipAddr from_addr,
+          template (value) SipAddr to_addr,
+          template (value) Via via,
           integer seq_nr,
           template (omit) charstring body) := {
        requestLine := ts_SIP_ReqLine(ACK_E, to_addr.addr.nameAddr.addrSpec),
        msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr,
                                     ts_Contact_SipAddr(from_addr),
                                     "ACK", seq_nr,
-                                    
ts_Via_from(from_addr.addr.nameAddr.addrSpec.hostPort),
+                                    via,
                                     f_ContentTypeOrOmit(ts_CT_SDP, body)),
        messageBody := body,
        payload := omit
 }
 template (present) PDU_SIP_Request
-tr_SIP_ACK(template CallidString call_id,
+tr_SIP_ACK(template (present) SipUrl uri,
+          template CallidString call_id,
           template SipAddr from_addr,
           template SipAddr to_addr,
+          template Via via,
           template integer seq_nr,
           template charstring body) := {
-       requestLine := tr_SIP_ReqLine(ACK_E, to_addr.addr.nameAddr.addrSpec),
+       requestLine := tr_SIP_ReqLine(ACK_E, uri),
        msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
-                                    
tr_Via_from(tr_HostPort(from_addr.addr.nameAddr.addrSpec.hostPort)),
+                                    via,
                                     "ACK", *, seq_nr),
        messageBody := body,
        payload := omit
 }

 template (value) PDU_SIP_Response
-ts_SIP_Response(CallidString call_id,
-               SipAddr from_addr,
-               SipAddr to_addr,
+ts_SIP_Response(template (value) CallidString call_id,
+               template (value) SipAddr from_addr,
+               template (value) SipAddr to_addr,
                charstring method,
                integer status_code,
                integer seq_nr,
@@ -626,6 +694,23 @@
        payload := omit
 }

+/* 180 Ringing */
+template (value) PDU_SIP_Response
+ts_SIP_Response_Ringing(
+       template (value) CallidString call_id,
+       template (value) SipAddr from_addr,
+       template (value) SipAddr to_addr,
+       Via via,
+       integer seq_nr,
+       charstring method := "INVITE",
+       template (omit) charstring body := omit) := {
+       statusLine := ts_SIP_StatusLine(180, "Ringing"),
+       msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, 
seq_nr,
+                                    via, f_ContentTypeOrOmit(ts_CT_SDP, body)),
+       messageBody := body,
+       payload := omit
+}
+
 template (present) PDU_SIP_Response
 tr_SIP_Response(template CallidString call_id,
                template SipAddr from_addr,
@@ -645,9 +730,9 @@
        payload := omit
 }

-/* Expect during first REGISTER when authorization is required: */
+/* Expect during first REGISTER/INVITE/... when authorization is required: */
 template (present) PDU_SIP_Response
-tr_SIP_Response_REGISTER_Unauthorized(
+tr_SIP_Response_Unauthorized(
        template CallidString call_id,
        template SipAddr from_addr,
        template SipAddr to_addr,
@@ -668,6 +753,50 @@
        payload := omit
 }

+/* 100 Trying */
+template (present) PDU_SIP_Response
+tr_SIP_Response_Trying(
+       template CallidString call_id,
+       template SipAddr from_addr,
+       template SipAddr to_addr,
+       template (present) Via via := tr_Via_from(?),
+       template integer seq_nr := ?,
+       template charstring method := "INVITE",
+       template integer status_code := 100,
+       template charstring reason := "Trying",
+       template charstring body := *) := {
+       statusLine := tr_SIP_StatusLine(status_code, reason),
+       msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, omit,
+                                    via,
+                                    method, *, seq_nr),
+       messageBody := body,
+       payload := omit
+}
+
+/* 180 Ringing */
+template (present) PDU_SIP_Response
+tr_SIP_Response_Ringing(
+       template CallidString call_id,
+       template SipAddr from_addr,
+       template SipAddr to_addr,
+       template (present) Via via := tr_Via_from(?),
+       template integer seq_nr := ?,
+       template charstring method := "INVITE",
+       template integer status_code := 180,
+       template charstring reason := "Ringing",
+       template charstring body := *) := {
+       statusLine := tr_SIP_StatusLine(status_code, reason),
+       msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
+                                    via,
+                                    method, *, seq_nr),
+       messageBody := body,
+       payload := omit
+}
+
+/****************
+ * FUNCTIONS:
+ ****************/
+
 function f_sip_param_find(GenericParam_List li,
                          template (present) charstring id := ?)
 return template (omit) GenericParam {
@@ -998,6 +1127,14 @@
        return f_rnd_int(2147483648)
 }

+function f_sip_next_seq_nr(integer seq_nr) return integer {
+       return (seq_nr + 1) mod 2147483648;
+}
+
+function f_sip_Request_inc_seq_nr(inout template (value) PDU_SIP_Request req) {
+       req.msgHeader.cSeq.seqNumber := 
f_sip_next_seq_nr(valueof(req.msgHeader.cSeq.seqNumber));
+}
+
 /* Tags shall have at least 32 bit of randomness */
 function f_sip_rand_tag() return charstring {
        var integer rnd_int := f_rnd_int(4294967296);
diff --git a/sip/SIP_Tests.ttcn b/sip/SIP_Tests.ttcn
index 4c6be1c..95f09e8 100644
--- a/sip/SIP_Tests.ttcn
+++ b/sip/SIP_Tests.ttcn
@@ -122,7 +122,7 @@
                unitdata_cb := refers(MNCC_Emulation.DummyUnitdataCallback)
        };

-       vc_MNCC := MNCC_Emulation_CT.create(id);
+       vc_MNCC := MNCC_Emulation_CT.create(id) alive;
        map(vc_MNCC:MNCC, system:MNCC_CODEC_PT);
        vc_MNCC.start(MNCC_Emulation.main(ops, id, mp_mncc, true));
 }
@@ -147,7 +147,7 @@
        var ConnHdlr vc_conn;
        var charstring id := testcasename();

-       vc_conn := ConnHdlr.create(id);
+       vc_conn := ConnHdlr.create(id) alive;

        connect(vc_conn:SIP, vc_SIP:CLIENT);
        connect(vc_conn:SIP_PROC, vc_SIP:CLIENT_PROC);
@@ -267,7 +267,9 @@

        /* OSC <- SIP: A party sends SIP invite for a MT-call into OSC */
        SIP.send(ts_SIP_INVITE(cp.comp.sip_call_id, cp.comp.sip_url_ext, 
cp.comp.sip_url_gsm,
-                               cp.comp.sip_seq_nr, cp.comp.sip_body));
+                              
ts_Via_from(cp.comp.sip_url_ext.addr.nameAddr.addrSpec.hostPort),
+                              ts_Contact_SipAddr(cp.comp.sip_url_ext),
+                              cp.comp.sip_seq_nr, cp.comp.sip_body));
        if (cp.mncc_with_sdp) {
                /* We just sent SDP via SIP, now expect the same SDP in MNCC to 
the MSC */
                expect_sdp_to_msc := cp.comp.sip_body;
@@ -275,7 +277,7 @@

        /* OSC -> SIP */
        as_SIP_expect_resp(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, 
sip_addr_gsm,
-                                          
tr_Via_from(tr_HostPort(sip_addr_ext.addr.nameAddr.addrSpec.hostPort)),
+                                          
tr_Via_from(f_tr_HostPort_opt_defport(sip_addr_ext.addr.nameAddr.addrSpec.hostPort)),
                                           *,
                                           "INVITE", 100, ?, "Trying", *));

@@ -288,7 +290,9 @@
                }
        [] SIP.receive {
                setverdict(fail, "Received unexpected SIP response");
-               SIP.send(ts_SIP_ACK(cp.comp.sip_call_id, cp.comp.sip_url_ext, 
cp.comp.sip_url_gsm,
+               SIP.send(ts_SIP_ACK(cp.comp.sip_call_id,
+                                   cp.comp.sip_url_ext, cp.comp.sip_url_gsm,
+                                   
ts_Via_from(cp.comp.sip_url_ext.addr.nameAddr.addrSpec.hostPort),
                                    cp.comp.sip_seq_nr, omit));
                mtc.stop;
                }
@@ -331,7 +335,7 @@

        /* 180 Ringing should not contain any SDP. */
        as_SIP_expect_resp(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, 
sip_addr_gsm,
-                                          
tr_Via_from(tr_HostPort(sip_addr_ext.addr.nameAddr.addrSpec.hostPort)),
+                                          
tr_Via_from(f_tr_HostPort_opt_defport(sip_addr_ext.addr.nameAddr.addrSpec.hostPort)),
                                           *,
                                           "INVITE", 180, ?, "Ringing", omit));

@@ -347,14 +351,16 @@

        /* OSC -> SIP: OSC confirms call establishment to SIP side */
        as_SIP_expect_resp(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, 
sip_addr_gsm,
-                                          
tr_Via_from(tr_HostPort(sip_addr_ext.addr.nameAddr.addrSpec.hostPort)),
+                                          
tr_Via_from(f_tr_HostPort_opt_defport(sip_addr_ext.addr.nameAddr.addrSpec.hostPort)),
                                           contact := ?,
                                           method := "INVITE", status_code := 
200,
                                           seq_nr := ?, reason := "OK",
                                           body := expect_sdp_to_sip));

        /* OSC <- SIP: SIP world acknowledges "200 OK" */
-       SIP.send(ts_SIP_ACK(cp.comp.sip_call_id, cp.comp.sip_url_ext, 
cp.comp.sip_url_gsm,
+       SIP.send(ts_SIP_ACK(cp.comp.sip_call_id,
+                           cp.comp.sip_url_ext, cp.comp.sip_url_gsm,
+                           
ts_Via_from(cp.comp.sip_url_ext.addr.nameAddr.addrSpec.hostPort),
                            cp.comp.sip_seq_nr, omit));
        /* MSC <- OSC: OSC sends SETUP COMPL to MNCC (which triggers CC CONNECT 
ACK */
        MNCC.receive(tr_MNCC_SETUP_COMPL_req(cp.mncc_call_id)) -> value mncc {
@@ -430,7 +436,10 @@
                 * "a=sendrecv;" */
                expect_sdp_to_sip := pattern cn_sdp & "*";
        }
-       sip_req := f_SIP_expect_req(tr_SIP_INVITE(?, sip_addr_gsm, 
sip_addr_ext, ?, expect_sdp_to_sip));
+       sip_req := 
f_SIP_expect_req(tr_SIP_INVITE(sip_addr_ext.addr.nameAddr.addrSpec, ?,
+                                                 sip_addr_gsm, sip_addr_ext,
+                                                 
tr_Via_from(f_tr_HostPort_opt_defport(sip_addr_gsm.addr.nameAddr.addrSpec.hostPort)),
+                                                 ?, expect_sdp_to_sip));
        cp.comp.sip_url_gsm.params := sip_req.msgHeader.fromField.fromParams;
        cp.comp.sip_call_id := sip_req.msgHeader.callId.callid;
        seq_nr := sip_req.msgHeader.cSeq.seqNumber;
@@ -474,7 +483,12 @@
        /* MSC -> OSC: CC CONNECT ACK was received from MS */
        MNCC.send(ts_MNCC_SETUP_COMPL_ind(cp.mncc_call_id));
        /* OSC -> SIP: Acknowledge the call */
-       SIP.receive(tr_SIP_ACK(cp.comp.sip_call_id, sip_addr_gsm, sip_addr_ext, 
?, omit));
+       SIP.receive(tr_SIP_ACK(sip_addr_ext.addr.nameAddr.addrSpec,
+                              cp.comp.sip_call_id,
+                              sip_addr_gsm,
+                              sip_addr_ext,
+                              
tr_Via_from(f_tr_HostPort_opt_defport(sip_addr_gsm.addr.nameAddr.addrSpec.hostPort)),
+                              ?, omit));
 }

 /* Release call from the mobile side */
@@ -487,7 +501,10 @@
        MNCC.send(ts_MNCC_DISC_ind(cp.mncc_call_id, ts_MNCC_cause(0)));

        /* OSC -> SIP: Expect BYE from OSC to SIP side */
-       sip_req := f_SIP_expect_req(tr_SIP_BYE(cp.comp.sip_call_id, 
sip_addr_gsm, sip_addr_ext, ?, *));
+       sip_req := 
f_SIP_expect_req(tr_SIP_BYE(sip_addr_ext.addr.nameAddr.addrSpec,
+                                              cp.comp.sip_call_id, 
sip_addr_gsm, sip_addr_ext,
+                                              
tr_Via_from(f_tr_HostPort_opt_defport(sip_addr_gsm.addr.nameAddr.addrSpec.hostPort)),
+                                              ?, *));
        cp.comp.sip_url_gsm.params := sip_req.msgHeader.fromField.fromParams;

        /* OSC <- SIP: Acknowledge the BYE */
@@ -506,6 +523,7 @@
        var template SipAddr sip_addr_ext := 
tr_SipAddr_from_val(cp.comp.sip_url_ext);
        /* OSC <- SIP: SIP-side sends a BYE to OSC */
        SIP.send(ts_SIP_BYE(cp.comp.sip_call_id, cp.comp.sip_url_ext, 
cp.comp.sip_url_gsm,
+                           
ts_Via_from(cp.comp.sip_url_ext.addr.nameAddr.addrSpec.hostPort),
                            cp.comp.sip_seq_nr, omit));
        /* MSC <- OSC: Expect OSC to cause MNCC Disconnect Request */
        MNCC.receive(tr_MNCC_DISC_req(cp.mncc_call_id));
@@ -513,7 +531,7 @@
        MNCC.send(ts_MNCC_REL_ind(cp.mncc_call_id, ts_MNCC_cause(0)));
        /* OSC -> SIP: Confirmation to SIP side */
        as_SIP_expect_resp(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, 
sip_addr_gsm,
-                                          
tr_Via_from(tr_HostPort(sip_addr_ext.addr.nameAddr.addrSpec.hostPort)),
+                                          
tr_Via_from(f_tr_HostPort_opt_defport(sip_addr_ext.addr.nameAddr.addrSpec.hostPort)),
                                           *,
                                           "BYE", 200, cp.comp.sip_seq_nr, 
"OK", omit));
 }
@@ -682,7 +700,10 @@
        timer T := 10.0;
        T.start;
        alt {
-       [] SIP.receive(tr_SIP_INVITE(?, sip_addr_gsm, sip_addr_ext, ?, ?)) {
+       [] SIP.receive(tr_SIP_INVITE(sip_addr_ext.addr.nameAddr.addrSpec, ?,
+                                    sip_addr_gsm, sip_addr_ext,
+                                    
tr_Via_from(f_tr_HostPort_opt_defport(sip_addr_gsm.addr.nameAddr.addrSpec.hostPort)),
+                                    ?, ?)) {
                setverdict(fail, "Received unexpected INVITE");
                }
        [] T.timeout {

--
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/36547?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: Ic5827a3e94b06fbc57f6405bf0f0aa6598c5d1fe
Gerrit-Change-Number: 36547
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pes...@sysmocom.de>
Gerrit-MessageType: newchange

Reply via email to