sip: Add SIP_Emulation and first osmo-sip-connector test case
Change-Id: Ifd47b0d48c609b4a678ea47aa7f89f5c12e6c0d2
This commit is contained in:
parent
a63b91017a
commit
afec471557
|
@ -193,7 +193,7 @@ runs on MNCC_Emulation_CT {
|
|||
}
|
||||
|
||||
|
||||
function f_connect(charstring sock) runs on MNCC_Emulation_CT {
|
||||
private function f_connect(charstring sock) runs on MNCC_Emulation_CT {
|
||||
var UD_connect_result res;
|
||||
timer T := 5.0;
|
||||
|
||||
|
@ -215,6 +215,40 @@ function f_connect(charstring sock) runs on MNCC_Emulation_CT {
|
|||
}
|
||||
}
|
||||
|
||||
private function f_listen(charstring sock) runs on MNCC_Emulation_CT {
|
||||
var UD_listen_result res;
|
||||
var UD_connected udc;
|
||||
timer T := 5.0;
|
||||
|
||||
T.start;
|
||||
MNCC.send(UD_listen:{sock});
|
||||
alt {
|
||||
[] MNCC.receive(UD_listen_result:?) -> value res {
|
||||
if (ispresent(res.result) and ispresent(res.result.result_code) and res.result.result_code == ERROR) {
|
||||
setverdict(fail, "Error listening to MNCC socket", res);
|
||||
self.stop;
|
||||
} else {
|
||||
g_mncc_ud_id := res.id;
|
||||
}
|
||||
}
|
||||
[] T.timeout {
|
||||
setverdict(fail, "Timeout listening to MNCC socket");
|
||||
self.stop;
|
||||
}
|
||||
}
|
||||
|
||||
T.start;
|
||||
alt {
|
||||
[] MNCC.receive(UD_connected:?) -> value udc {
|
||||
g_mncc_ud_id := res.id;
|
||||
}
|
||||
[] T.timeout {
|
||||
setverdict(fail, "Timeout waiting for MNCC connection");
|
||||
self.stop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* call-back type, to be provided by specific implementation; called when new SCCP connection
|
||||
* arrives */
|
||||
type function MnccCreateCallback(MNCC_PDU conn_ind, charstring id)
|
||||
|
@ -228,9 +262,14 @@ type record MnccOps {
|
|||
MnccUnitdataCallback unitdata_cb
|
||||
}
|
||||
|
||||
function main(MnccOps ops, charstring id, charstring sock) runs on MNCC_Emulation_CT {
|
||||
function main(MnccOps ops, charstring id, charstring sock, boolean role_server := false)
|
||||
runs on MNCC_Emulation_CT {
|
||||
|
||||
f_connect(sock);
|
||||
if (role_server) {
|
||||
f_listen(sock);
|
||||
} else {
|
||||
f_connect(sock);
|
||||
}
|
||||
f_expect_table_init();
|
||||
f_call_table_init();
|
||||
|
||||
|
@ -289,15 +328,19 @@ function main(MnccOps ops, charstring id, charstring sock) runs on MNCC_Emulatio
|
|||
f_call_table_del(call_id);
|
||||
}
|
||||
|
||||
/* Client -> MNCC Socket: SETUP.req: forward + add call table entry */
|
||||
[] MNCC_CLIENT.receive(MNCC_PDU:{msg_type := MNCC_SETUP_REQ, u:=?}) -> value mncc sender vc_conn {
|
||||
/* add to call table */
|
||||
f_call_table_add(vc_conn, f_mncc_get_call_id(mncc));
|
||||
/* Client -> MNCC Socket: Normal message */
|
||||
[] MNCC_CLIENT.receive(MNCC_PDU:?) -> value mncc sender vc_conn {
|
||||
if (mncc.msg_type == MNCC_SETUP_REQ and not role_server) {
|
||||
/* ConnHdlr -> MNCC Server: SETUP.req: add to call table */
|
||||
f_call_table_add(vc_conn, f_mncc_get_call_id(mncc));
|
||||
} else if (mncc.msg_type == MNCC_SETUP_IND and role_server) {
|
||||
/* ConnHdlr -> MNCC Client: SETUP.ind: add to call table */
|
||||
f_call_table_add(vc_conn, f_mncc_get_call_id(mncc));
|
||||
}
|
||||
/* forward to MNCC socket */
|
||||
MNCC.send(t_SD_MNCC(g_mncc_ud_id, mncc));
|
||||
}
|
||||
|
||||
/* Client -> MNCC Socket: Normal message */
|
||||
[] MNCC_CLIENT.receive(MNCC_PDU:?) -> value mncc sender vc_conn {
|
||||
/* forward to MNCC socket */
|
||||
MNCC.send(t_SD_MNCC(g_mncc_ud_id, mncc));
|
||||
|
|
|
@ -561,7 +561,38 @@ template MNCC_PDU tr_MNCC_SETUP_ind(template uint32_t call_id := ?, template MNC
|
|||
lchan_mode := ?
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
template (value) MNCC_PDU ts_MNCC_SETUP_ind(uint32_t call_id, MNCC_number called,
|
||||
template (omit) MNCC_number calling := omit,
|
||||
template (omit) charstring imsi := omit,
|
||||
template (value) MNCC_bearer_cap bcap := ts_MNCC_bcap_voice) := {
|
||||
msg_type := MNCC_SETUP_IND,
|
||||
u := {
|
||||
signal := { /* See 24.008 9.3.23.2 */
|
||||
callref := call_id,
|
||||
bearer_cap := valueof(bcap), /* mandatory */
|
||||
called := called, /* mandatory */
|
||||
calling := calling, /* optional */
|
||||
redirecting := omit,
|
||||
connected := omit,
|
||||
cause := omit,
|
||||
progress := omit,
|
||||
useruser := omit, /* optional */
|
||||
facility := omit, /* optional */
|
||||
cccap := omit, /* optional */
|
||||
ssversion := omit, /* optional */
|
||||
clir_sup := 0, /* optional */
|
||||
clir_inv := 0, /* optional */
|
||||
signal := omit,
|
||||
keypad := omit,
|
||||
more := 0,
|
||||
notify := 0,
|
||||
emergency := omit,
|
||||
imsi := imsi,
|
||||
lchan_type := 0,
|
||||
lchan_mode := 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* MO: MSC <- MNCC: SETUP.cnf; Response to SETUP.ind */
|
||||
|
|
|
@ -0,0 +1,408 @@
|
|||
module SIP_Emulation {
|
||||
|
||||
/* SIP Emulation, runs on top of SIPmsg_PT. It multiplexes/demultiplexes
|
||||
* the individual calls, so there can be separate TTCN-3 components handling
|
||||
* each of the calls
|
||||
*
|
||||
* The SIP_Emulation.main() function processes SIP message from the SIPmsg
|
||||
* socket via the SIPmsg_PT, and dispatches them to the per-connection components.
|
||||
*
|
||||
* Outbound SIP calls are initiated by sending a PDU_SIP_Request messages
|
||||
* to the component running the SIP_Emulation.main() function.
|
||||
*
|
||||
* For each new inbound call, the SipOps.create_cb() is called. It can create
|
||||
* or resolve a TTCN-3 component, and returns a component reference to which that inbound
|
||||
* call is routed/dispatched.
|
||||
*
|
||||
* If a pre-existing component wants to register to handle a future inbound call, it can
|
||||
* do so by registering an "expect" with the expected destination phone number. This is e.g. useful
|
||||
* if you are simulating MNCC + SIP, and first trigger a connection from MNCC side in a
|
||||
* component which then subsequently should also handle the SIP emulation.
|
||||
*
|
||||
* (C) 2018 by Harald Welte <laforge@gnumonks.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Released under the terms of GNU General Public License, Version 2 or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
import from SIPmsg_Types all;
|
||||
import from SIPmsg_PortType all;
|
||||
|
||||
type component SIP_ConnHdlr {
|
||||
/* ports towards SIP Emulation core / call dispatcher */
|
||||
port SIP_Conn_PT SIP;
|
||||
port SIPEM_PROC_PT SIP_PROC;
|
||||
}
|
||||
|
||||
/* port between individual per-call components and this dispatcher */
|
||||
type port SIP_Conn_PT message {
|
||||
inout PDU_SIP_Request, PDU_SIP_Response;
|
||||
} with { extension "internal" };
|
||||
|
||||
/* represents a single SIP Call */
|
||||
type record CallData {
|
||||
/* reference to the instance of the per-connection component */
|
||||
SIP_ConnHdlr comp_ref,
|
||||
CallidString call_id
|
||||
}
|
||||
|
||||
type component SIP_Emulation_CT {
|
||||
/* SIP test port on bottom side */
|
||||
port SIPmsg_PT SIP;
|
||||
/* SIP port to the per-call clients */
|
||||
port SIP_Conn_PT CLIENT;
|
||||
|
||||
var CallData SipCallTable[16];
|
||||
var ExpectData SipExpectTable[16];
|
||||
|
||||
/* procedure based port to register for incoming connections */
|
||||
port SIPEM_PROC_PT CLIENT_PROC;
|
||||
};
|
||||
|
||||
private function f_sip_init() runs on SIP_Emulation_CT {
|
||||
map(self:SIP, system:SIP);
|
||||
}
|
||||
|
||||
template RequestLine tr_ReqLine(template Method method) := {
|
||||
method := method,
|
||||
requestUri := ?,
|
||||
sipVersion := ?
|
||||
}
|
||||
|
||||
template PDU_SIP_Request tr_SIP_INVITE := {
|
||||
requestLine := tr_ReqLine(INVITE_E),
|
||||
msgHeader := t_SIP_msgHeader_any,
|
||||
messageBody := *,
|
||||
payload := *
|
||||
}
|
||||
|
||||
|
||||
template SipUrl tr_SIP_Url(template charstring user_or_num,
|
||||
template charstring host := *,
|
||||
template integer portField := *) := {
|
||||
scheme := "sip",
|
||||
userInfo := {
|
||||
userOrTelephoneSubscriber := user_or_num,
|
||||
password := *
|
||||
},
|
||||
hostPort := {
|
||||
host := host,
|
||||
portField := portField
|
||||
},
|
||||
urlParameters := *,
|
||||
headers := *
|
||||
}
|
||||
template (value) SipUrl ts_SIP_Url(charstring user_or_num,
|
||||
template (omit) charstring host := omit,
|
||||
template (omit) integer portField := omit) := {
|
||||
scheme := "sip",
|
||||
userInfo := {
|
||||
userOrTelephoneSubscriber := user_or_num,
|
||||
password := omit
|
||||
},
|
||||
hostPort := {
|
||||
host := host,
|
||||
portField := portField
|
||||
},
|
||||
urlParameters := omit,
|
||||
headers := omit
|
||||
}
|
||||
|
||||
template Addr_Union tr_SIP_Addr(template SipUrl sip_url) := {
|
||||
nameAddr := {
|
||||
displayName := *,
|
||||
addrSpec := sip_url
|
||||
}
|
||||
}
|
||||
template (value) Addr_Union ts_SIP_Addr(template (value) SipUrl sip_url) := {
|
||||
nameAddr := {
|
||||
displayName := omit,
|
||||
addrSpec := sip_url
|
||||
}
|
||||
}
|
||||
|
||||
template To tr_SIP_To(template Addr_Union addr) := {
|
||||
fieldName := TO_E,
|
||||
addressField := addr,
|
||||
toParams := *
|
||||
}
|
||||
template (value) To ts_SIP_To(template (value) Addr_Union addr) := {
|
||||
fieldName := TO_E,
|
||||
addressField := addr,
|
||||
toParams := omit
|
||||
}
|
||||
|
||||
/* resolve component reference by connection ID */
|
||||
private function f_call_id_known(CallidString call_id)
|
||||
runs on SIP_Emulation_CT return boolean {
|
||||
var integer i;
|
||||
for (i := 0; i < sizeof(SipCallTable); i := i+1) {
|
||||
if (SipCallTable[i].call_id == call_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* resolve component reference by connection ID */
|
||||
private function f_comp_by_call_id(CallidString call_id)
|
||||
runs on SIP_Emulation_CT return SIP_ConnHdlr {
|
||||
var integer i;
|
||||
for (i := 0; i < sizeof(SipCallTable); i := i+1) {
|
||||
if (SipCallTable[i].call_id == call_id) {
|
||||
return SipCallTable[i].comp_ref;
|
||||
}
|
||||
}
|
||||
setverdict(fail, "SIP Call table not found by SIP Call ID ", call_id);
|
||||
self.stop;
|
||||
}
|
||||
|
||||
/* resolve connection ID by component reference */
|
||||
private function f_call_id_by_comp(SIP_ConnHdlr client)
|
||||
runs on SIP_Emulation_CT return CallidString {
|
||||
for (var integer i := 0; i < sizeof(SipCallTable); i := i+1) {
|
||||
if (SipCallTable[i].comp_ref == client) {
|
||||
return SipCallTable[i].call_id;
|
||||
}
|
||||
}
|
||||
setverdict(fail, "SIP Call table not found by component ", client);
|
||||
self.stop;
|
||||
}
|
||||
|
||||
private function f_expect_table_init()
|
||||
runs on SIP_Emulation_CT {
|
||||
for (var integer i := 0; i < sizeof(SipExpectTable); i := i+1) {
|
||||
SipExpectTable[i].sip_to := omit;
|
||||
SipExpectTable[i].vc_conn := null;
|
||||
}
|
||||
}
|
||||
|
||||
private function f_call_table_init()
|
||||
runs on SIP_Emulation_CT {
|
||||
for (var integer i := 0; i < sizeof(SipCallTable); i := i+1) {
|
||||
SipCallTable[i].comp_ref := null;
|
||||
SipCallTable[i].call_id := "";
|
||||
}
|
||||
}
|
||||
|
||||
private function f_call_table_add(SIP_ConnHdlr comp_ref, CallidString call_id)
|
||||
runs on SIP_Emulation_CT {
|
||||
for (var integer i := 0; i < sizeof(SipCallTable); i := i+1) {
|
||||
if (SipCallTable[i].call_id == "") {
|
||||
SipCallTable[i].comp_ref := comp_ref;
|
||||
SipCallTable[i].call_id := call_id;
|
||||
log("Added SIP Call Table entry [", i, "] for ", call_id, " at ", comp_ref);
|
||||
return;
|
||||
}
|
||||
}
|
||||
setverdict(fail, "SIP Call table full");
|
||||
self.stop;
|
||||
}
|
||||
|
||||
private function f_call_table_del(CallidString call_id)
|
||||
runs on SIP_Emulation_CT {
|
||||
for (var integer i := 0; i < sizeof(SipCallTable); i := i+1) {
|
||||
if (SipCallTable[i].call_id == call_id) {
|
||||
SipCallTable[i].comp_ref := null;
|
||||
SipCallTable[i].call_id := "";
|
||||
log("Deleted SIP Call Table entry [", i, "] for ", call_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
setverdict(fail, "SIP Call table attempt to delete non-existant ", call_id);
|
||||
self.stop;
|
||||
}
|
||||
|
||||
/* call-back type, to be provided by specific implementation; called when new call connection
|
||||
* arrives */
|
||||
type function SipCreateCallback(PDU_SIP_Request sip_req, charstring id)
|
||||
runs on SIP_Emulation_CT return SIP_ConnHdlr;
|
||||
|
||||
type record SipOps {
|
||||
SipCreateCallback create_cb
|
||||
};
|
||||
|
||||
function f_init_sip(inout SIP_Emulation_CT ct, charstring id) {
|
||||
id := id & "-SIP";
|
||||
|
||||
var SipOps ops := {
|
||||
create_cb := refers(SIP_Emulation.ExpectedCreateCallback)
|
||||
};
|
||||
|
||||
ct := SIP_Emulation_CT.create(id);
|
||||
map(ct:SIP, system:SIP);
|
||||
ct.start(SIP_Emulation.main(ops, id));
|
||||
}
|
||||
|
||||
function main(SipOps ops, charstring id)
|
||||
runs on SIP_Emulation_CT {
|
||||
|
||||
f_sip_init();
|
||||
f_expect_table_init();
|
||||
f_call_table_init();
|
||||
|
||||
while (true) {
|
||||
var SIP_ConnHdlr vc_hdlr, vc_conn;
|
||||
var PDU_SIP_Request sip_req;
|
||||
var PDU_SIP_Response sip_resp;
|
||||
var SipUrl sip_to;
|
||||
|
||||
alt {
|
||||
/* SIP INVITE was received on SIP socket/port */
|
||||
[] SIP.receive(tr_SIP_INVITE) -> value sip_req {
|
||||
var CallidString call_id := sip_req.msgHeader.callId.callid;
|
||||
if (f_call_id_known(call_id)) {
|
||||
/* re-invite? */
|
||||
vc_conn := f_comp_by_call_id(call_id);
|
||||
} else {
|
||||
/* new INVITE: check expect */
|
||||
vc_conn := ops.create_cb.apply(sip_req, id);
|
||||
f_call_table_add(vc_conn, call_id);
|
||||
}
|
||||
CLIENT.send(sip_req) to vc_conn;
|
||||
}
|
||||
/* other SIP request was received on SIP socket/port */
|
||||
[] SIP.receive(PDU_SIP_Request:?) -> value sip_req {
|
||||
var CallidString call_id := sip_req.msgHeader.callId.callid;
|
||||
if (f_call_id_known(call_id)) {
|
||||
vc_conn := f_comp_by_call_id(call_id);
|
||||
CLIENT.send(sip_req) to vc_conn;
|
||||
} else {
|
||||
setverdict(fail, "SIP Request for unknown call ", call_id);
|
||||
self.stop;
|
||||
}
|
||||
}
|
||||
/* SIP response was received on SIP socket/port */
|
||||
[] SIP.receive(PDU_SIP_Response:?) -> value sip_resp {
|
||||
var CallidString call_id := sip_resp.msgHeader.callId.callid;
|
||||
if (f_call_id_known(call_id)) {
|
||||
vc_conn := f_comp_by_call_id(call_id);
|
||||
CLIENT.send(sip_resp) to vc_conn;
|
||||
} else {
|
||||
setverdict(fail, "SIP Response for unknown call ", call_id);
|
||||
self.stop;
|
||||
}
|
||||
}
|
||||
|
||||
/* a ConnHdlr is sending us a SIP INVITE: Forward to SIP port */
|
||||
[] CLIENT.receive(tr_SIP_INVITE) -> value sip_req sender vc_conn {
|
||||
var CallidString call_id := sip_req.msgHeader.callId.callid;
|
||||
if (f_call_id_known(call_id)) {
|
||||
/* re-invite? */
|
||||
vc_conn := f_comp_by_call_id(call_id);
|
||||
} else {
|
||||
/* new INVITE: add to table */
|
||||
f_call_table_add(vc_conn, call_id);
|
||||
}
|
||||
SIP.send(sip_req);
|
||||
}
|
||||
/* a ConnHdlr is sending us a SIP request: Forward to SIP port */
|
||||
[] CLIENT.receive(PDU_SIP_Request:?) -> value sip_req sender vc_conn {
|
||||
SIP.send(sip_req);
|
||||
}
|
||||
/* a ConnHdlr is sending us a SIP request: Forward to SIP port */
|
||||
[] CLIENT.receive(PDU_SIP_Response:?) -> value sip_resp sender vc_conn {
|
||||
SIP.send(sip_resp);
|
||||
}
|
||||
|
||||
[] CLIENT_PROC.getcall(SIPEM_register:{?,?}) -> param(sip_to, vc_hdlr) {
|
||||
f_create_expect(sip_to, vc_hdlr);
|
||||
CLIENT_PROC.reply(SIPEM_register:{sip_to, vc_hdlr});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* "Expect" Handling (mapping for expected incoming SIP callds from IUT)
|
||||
***********************************************************************/
|
||||
|
||||
/* data about an expected future incoming connection */
|
||||
type record ExpectData {
|
||||
/* SIP "To" (destination number) based on which we can match */
|
||||
SipUrl sip_to optional,
|
||||
/* component reference registered for the connection */
|
||||
SIP_ConnHdlr vc_conn
|
||||
}
|
||||
|
||||
/* procedure based port to register for incoming calls */
|
||||
signature SIPEM_register(SipUrl sip_to, SIP_ConnHdlr vc_conn);
|
||||
|
||||
type port SIPEM_PROC_PT procedure {
|
||||
inout SIPEM_register;
|
||||
} with { extension "internal" };
|
||||
|
||||
|
||||
/* CreateCallback that can be used as create_cb and will use the expect table */
|
||||
function ExpectedCreateCallback(PDU_SIP_Request sip_req, charstring id)
|
||||
runs on SIP_Emulation_CT return SIP_ConnHdlr {
|
||||
var SIP_ConnHdlr ret := null;
|
||||
var SipUrl sip_to;
|
||||
var integer i;
|
||||
|
||||
if (sip_req.requestLine.method != INVITE_E) {
|
||||
setverdict(fail, "SIP ExpectedCreateCallback needs INVITE");
|
||||
return ret;
|
||||
}
|
||||
sip_to := sip_req.msgHeader.toField.addressField.nameAddr.addrSpec;
|
||||
|
||||
for (i := 0; i < sizeof(SipExpectTable); i := i+1) {
|
||||
if (not ispresent(SipExpectTable[i].sip_to)) {
|
||||
continue;
|
||||
}
|
||||
/* build a template, use '*' for all 'omit' values */
|
||||
var template SipUrl t_exp := SipExpectTable[i].sip_to;
|
||||
if (not ispresent(t_exp.hostPort.host)) {
|
||||
t_exp.hostPort.host := *;
|
||||
}
|
||||
if (not ispresent(t_exp.hostPort.portField)) {
|
||||
t_exp.hostPort.portField := *;
|
||||
}
|
||||
if (not ispresent(t_exp.urlParameters)) {
|
||||
t_exp.urlParameters := *;
|
||||
}
|
||||
if (not ispresent(t_exp.headers)) {
|
||||
t_exp.headers := *;
|
||||
}
|
||||
/* match against the constructed template */
|
||||
if (match(sip_to, t_exp)) {
|
||||
ret := SipExpectTable[i].vc_conn;
|
||||
/* release this entry to be used again */
|
||||
SipExpectTable[i].sip_to := omit;
|
||||
SipExpectTable[i].vc_conn := null;
|
||||
log("Found SipExpect[", i, "] for ", sip_to, " handled at ", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
setverdict(fail, "Couldn't find SipExpect for incoming call ", sip_to);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* server/emulation side function to create expect */
|
||||
private function f_create_expect(SipUrl sip_to, SIP_ConnHdlr hdlr)
|
||||
runs on SIP_Emulation_CT {
|
||||
var integer i;
|
||||
for (i := 0; i < sizeof(SipExpectTable); i := i+1) {
|
||||
if (not ispresent(SipExpectTable[i].sip_to)) {
|
||||
SipExpectTable[i].sip_to := sip_to;
|
||||
SipExpectTable[i].vc_conn := hdlr;
|
||||
log("Created SipExpect[", i, "] for ", sip_to, " to be handled at ", hdlr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
setverdict(fail, "No space left in SipExpectTable");
|
||||
}
|
||||
|
||||
/* client/conn_hdlr side function to use procedure port to create expect in emulation */
|
||||
function f_create_sip_expect(SipUrl sip_to) runs on SIP_ConnHdlr {
|
||||
SIP_PROC.call(SIPEM_register:{sip_to, self}) {
|
||||
[] SIP_PROC.getreply(SIPEM_register:{?,?}) {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
[ORDERED_INCLUDE]
|
||||
# Common configuration, shared between test suites
|
||||
"../Common.cfg"
|
||||
# testsuite specific configuration, not expected to change
|
||||
"./SIP_Tests.default"
|
||||
|
||||
# Local configuration below
|
||||
|
||||
[LOGGING]
|
||||
|
||||
[TESTPORT_PARAMETERS]
|
||||
|
||||
[MODULE_PARAMETERS]
|
||||
|
||||
[MAIN_CONTROLLER]
|
||||
|
||||
[EXECUTE]
|
||||
SIP_Tests.control
|
|
@ -0,0 +1,30 @@
|
|||
[LOGGING]
|
||||
FileMask := LOG_ALL | TTCN_MATCHING;
|
||||
|
||||
"IPA-CTRL-IPA".FileMask := ERROR | WARNING;
|
||||
mtc.FileMask := ERROR | WARNING;
|
||||
|
||||
[TESTPORT_PARAMETERS]
|
||||
"SIP_Test-MNCC".MNCC.socket_type := "SEQPACKET";
|
||||
*.SIPVTY.CTRL_MODE := "client"
|
||||
*.SIPVTY.CTRL_HOSTNAME := "127.0.0.1"
|
||||
*.SIPVTY.CTRL_PORTNUM := "4256"
|
||||
*.SIPVTY.CTRL_LOGIN_SKIPPED := "yes"
|
||||
*.SIPVTY.CTRL_DETECT_SERVER_DISCONNECTED := "yes"
|
||||
*.SIPVTY.CTRL_READMODE := "buffered"
|
||||
*.SIPVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
|
||||
*.SIPVTY.PROMPT1 := "OsmoMNCC> "
|
||||
|
||||
*.SIP.local_sip_port := "5060"
|
||||
*.SIP.default_local_address := "127.0.0.2"
|
||||
*.SIP.default_sip_protocol := "UDP"
|
||||
*.SIP.default_dest_port := "5060"
|
||||
*.SIP.default_dest_address := "127.0.0.1"
|
||||
|
||||
|
||||
[MODULE_PARAMETERS]
|
||||
Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoMNCC";
|
||||
|
||||
[MAIN_CONTROLLER]
|
||||
|
||||
[EXECUTE]
|
|
@ -0,0 +1,173 @@
|
|||
module SIP_Tests {
|
||||
|
||||
import from General_Types all;
|
||||
import from Osmocom_Types all;
|
||||
|
||||
import from Osmocom_CTRL_Functions all;
|
||||
import from Osmocom_CTRL_Types all;
|
||||
import from Osmocom_CTRL_Adapter all;
|
||||
|
||||
import from TELNETasp_PortType all;
|
||||
import from Osmocom_VTY_Functions all;
|
||||
|
||||
import from MNCC_Emulation all;
|
||||
import from MNCC_Types all;
|
||||
|
||||
import from SDP_Types all;
|
||||
|
||||
import from SIP_Emulation all;
|
||||
import from SIPmsg_Types all;
|
||||
|
||||
modulepar {
|
||||
//charstring mp_local_host := "127.0.0.2;
|
||||
charstring mp_osmosip_host := "127.0.0.1";
|
||||
integer mp_osmosip_port_ctrl := -1; /* RFU */
|
||||
charstring mp_mncc := "/tmp/mncc";
|
||||
}
|
||||
|
||||
type component test_CT extends CTRL_Adapter_CT {
|
||||
var MNCC_Emulation_CT vc_MNCC;
|
||||
var SIP_Emulation_CT vc_SIP;
|
||||
|
||||
port TELNETasp_PT SIPVTY;
|
||||
}
|
||||
|
||||
type component ConnHdlr extends SIP_ConnHdlr, MNCC_ConnHdlr {
|
||||
var ConnHdlrPars g_pars;
|
||||
timer g_Tguard;
|
||||
}
|
||||
|
||||
type record ConnHdlrPars {
|
||||
float t_guard
|
||||
}
|
||||
|
||||
|
||||
function f_init_mncc(charstring id) runs on test_CT {
|
||||
id := id & "-MNCC";
|
||||
var MnccOps ops := {
|
||||
create_cb := refers(MNCC_Emulation.ExpectedCreateCallback),
|
||||
unitdata_cb := refers(MNCC_Emulation.DummyUnitdataCallback)
|
||||
};
|
||||
|
||||
vc_MNCC := MNCC_Emulation_CT.create(id);
|
||||
map(vc_MNCC:MNCC, system:MNCC_CODEC_PT);
|
||||
vc_MNCC.start(MNCC_Emulation.main(ops, id, mp_mncc, true));
|
||||
}
|
||||
|
||||
function f_init() runs on test_CT {
|
||||
//f_ipa_ctrl_start(mp_osmosip_host, mp_osmosip_port_ctrl);
|
||||
f_init_mncc("SIP_Test");
|
||||
log("end of f_init_mncc");
|
||||
f_init_sip(vc_SIP, "SIP_Test");
|
||||
log("end of f_init_sip");
|
||||
|
||||
map(self:SIPVTY, system:SIPVTY);
|
||||
f_vty_set_prompts(SIPVTY);
|
||||
f_vty_transceive(SIPVTY, "enable");
|
||||
log("end of f_init");
|
||||
}
|
||||
|
||||
type function void_fn(charstring id) runs on ConnHdlr;
|
||||
|
||||
function f_start_handler(void_fn fn, ConnHdlrPars pars)
|
||||
runs on test_CT return ConnHdlr {
|
||||
var ConnHdlr vc_conn;
|
||||
var charstring id := testcasename();
|
||||
|
||||
vc_conn := ConnHdlr.create(id);
|
||||
|
||||
connect(vc_conn:SIP, vc_SIP:CLIENT);
|
||||
connect(vc_conn:SIP_PROC, vc_SIP:CLIENT_PROC);
|
||||
|
||||
connect(vc_conn:MNCC, vc_MNCC:MNCC_CLIENT);
|
||||
connect(vc_conn:MNCC_PROC, vc_MNCC:MNCC_PROC);
|
||||
|
||||
vc_conn.start(f_handler_init(fn, id, pars));
|
||||
return vc_conn;
|
||||
}
|
||||
|
||||
private altstep as_Tguard() runs on ConnHdlr {
|
||||
[] g_Tguard.timeout {
|
||||
setverdict(fail, "Tguard timeout");
|
||||
self.stop;
|
||||
}
|
||||
}
|
||||
|
||||
private function f_handler_init(void_fn fn, charstring id, ConnHdlrPars pars)
|
||||
runs on ConnHdlr {
|
||||
g_pars := pars;
|
||||
g_Tguard.start(pars.t_guard);
|
||||
activate(as_Tguard());
|
||||
|
||||
/* call the user-supied test case function */
|
||||
fn.apply(id);
|
||||
}
|
||||
|
||||
|
||||
template (value) ConnHdlrPars t_Pars := {
|
||||
t_guard := 30.0
|
||||
}
|
||||
|
||||
private function f_TC_mo_setup(charstring id) runs on ConnHdlr {
|
||||
var PDU_SIP_Request sip_req;
|
||||
|
||||
var MNCC_number dst := valueof(ts_MNCC_number("01234567"));
|
||||
var MNCC_number src := valueof(ts_MNCC_number("112"));
|
||||
|
||||
f_create_sip_expect(valueof(ts_SIP_Url("+01234567")));
|
||||
|
||||
log("sending mncc setup");
|
||||
MNCC.send(ts_MNCC_SETUP_ind(2342, dst, src, "262420123456789"));
|
||||
|
||||
MNCC.receive(tr_MNCC_RTP_CREATE(2342));
|
||||
MNCC.send(ts_MNCC_RTP_CREATE(2342));
|
||||
|
||||
SIP.receive(PDU_SIP_Request:?) -> value sip_req {
|
||||
log(sip_req);
|
||||
}
|
||||
}
|
||||
|
||||
testcase TC_mo_setup() runs on test_CT {
|
||||
var ConnHdlrPars pars;
|
||||
var ConnHdlr vc_conn;
|
||||
|
||||
f_init();
|
||||
|
||||
pars := valueof(t_Pars);
|
||||
vc_conn := f_start_handler(refers(f_TC_mo_setup), pars);
|
||||
vc_conn.done;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* SIP specifics */
|
||||
|
||||
const integer c_SIP_PORT := 5060;
|
||||
|
||||
template (value) SIP_comm_adress ts_SipAddr(charstring rhost,
|
||||
template (omit) charstring lhost := omit,
|
||||
integer rport := c_SIP_PORT,
|
||||
integer lport := c_SIP_PORT,
|
||||
SIP_com_prot prot := UDP_E) := {
|
||||
remote_host := rhost,
|
||||
remote_port := rport,
|
||||
local_host := lhost,
|
||||
local_port := lport,
|
||||
protocol := prot
|
||||
}
|
||||
|
||||
template (value) ASP_SIP_open ts_SIP_open(SIP_comm_adress addr) := {
|
||||
addr := addr
|
||||
}
|
||||
|
||||
|
||||
|
||||
control {
|
||||
execute( TC_mo_setup() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
#!/bin/bash
|
||||
|
||||
BASEDIR=../deps
|
||||
|
||||
. ../gen_links.sh.inc
|
||||
|
||||
DIR=$BASEDIR/titan.TestPorts.UNIX_DOMAIN_SOCKETasp/src
|
||||
FILES="UD_PT.cc UD_PT.hh UD_PortType.ttcn UD_Types.ttcn"
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
|
||||
FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h"
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
|
||||
FILES="Socket_API_Definitions.ttcn"
|
||||
gen_links $DIR $FILES
|
||||
|
||||
# Required by MGCP and IPA
|
||||
DIR=$BASEDIR/titan.TestPorts.IPL4asp/src
|
||||
FILES="IPL4asp_Functions.ttcn IPL4asp_PT.cc IPL4asp_PT.hh IPL4asp_PortType.ttcn IPL4asp_Types.ttcn IPL4asp_discovery.cc IPL4asp_protocol_L234.hh"
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=$BASEDIR/titan.ProtocolModules.SDP/src
|
||||
FILES="SDP_EncDec.cc SDP_Types.ttcn SDP_parse_.tab.c SDP_parse_.tab.h SDP_parse_parser.h SDP_parser.l
|
||||
SDP_parser.y lex.SDP_parse_.c"
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=$BASEDIR/titan.ProtocolModules.RTP/src
|
||||
FILES="RTP_EncDec.cc RTP_Types.ttcn"
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=$BASEDIR/titan.TestPorts.SIPmsg/src
|
||||
FILES="SIP_parse.h SIP_parse.y SIP_parse_.tab.h SIPmsg_PT.hh SIPmsg_Types.ttcn SIP_parse.l SIP_parse_.tab.c SIPmsg_PT.cc SIPmsg_PortType.ttcn lex.SIP_parse_.c"
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=$BASEDIR/titan.TestPorts.TELNETasp/src
|
||||
FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=../library
|
||||
FILES="General_Types.ttcn GSM_Types.ttcn Osmocom_Types.ttcn MNCC_Types.ttcn MNCC_EncDec.cc MNCC_CodecPort.ttcn mncc.h MNCC_Emulation.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc "
|
||||
FILES+="IPA_Types.ttcn IPA_Emulation.ttcnpp IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc "
|
||||
FILES+="Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn "
|
||||
FILES+="RTP_CodecPort.ttcn RTP_CodecPort_CtrlFunctDef.cc "
|
||||
FILES+="SIP_Emulation.ttcn "
|
||||
gen_links $DIR $FILES
|
||||
|
||||
ignore_pp_results
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/sh
|
||||
|
||||
FILES="*.ttcn *.ttcnpp TCCConversion.cc TCCInterface.cc UD_PT.cc MNCC_EncDec.cc IPL4asp_PT.cc
|
||||
IPL4asp_discovery.cc SDP_EncDec.cc RTP_EncDec.cc IPA_CodecPort_CtrlFunctDef.cc RTP_CodecPort_CtrlFunctDef.cc TELNETasp_PT.cc Native_FunctionDefs.cc SIPmsg_PT.cc *.c "
|
||||
|
||||
export CPPFLAGS_TTCN3=""
|
||||
|
||||
../regen-makefile.sh SIP_Tests.ttcn $FILES
|
Loading…
Reference in New Issue