forked from ttcn3/osmo-ttcn3-hacks
559 lines
16 KiB
Plaintext
559 lines
16 KiB
Plaintext
module SIP_Templates {
|
|
|
|
import from SIPmsg_Types all;
|
|
import from Osmocom_Types all;
|
|
|
|
/* wrapper type to encapsulate the Addr_Union + parameter list used in From, To. ... */
|
|
type record SipAddr {
|
|
Addr_Union addr,
|
|
SemicolonParam_List params optional
|
|
}
|
|
|
|
const charstring c_SIP_VERSION := "SIP/2.0";
|
|
|
|
template (value) SipUrl ts_SipUrl(template (value) HostPort host_port,
|
|
template (omit) UserInfo user_info := omit) := {
|
|
scheme := "sip",
|
|
userInfo := user_info,
|
|
hostPort := host_port,
|
|
urlParameters := omit,
|
|
headers := omit
|
|
}
|
|
template (present) SipUrl tr_SipUrl(template (present) HostPort host_port := ?,
|
|
template UserInfo user_info := *) := {
|
|
scheme := "sip",
|
|
userInfo := user_info,
|
|
hostPort := host_port,
|
|
urlParameters := *,
|
|
headers := *
|
|
}
|
|
|
|
template (value) SipUrl ts_SipUrlHost(template (value) charstring host)
|
|
:= ts_SipUrl(ts_HostPort(host));
|
|
|
|
// [20.10]
|
|
template (present) NameAddr tr_NameAddr(template (present) SipUrl addrSpec := ?,
|
|
template charstring displayName := *) := {
|
|
displayName := displayName,
|
|
addrSpec := addrSpec
|
|
}
|
|
template (value) NameAddr ts_NameAddr(template (value) SipUrl addrSpec,
|
|
template (omit) charstring displayName := omit) := {
|
|
displayName := displayName,
|
|
addrSpec := addrSpec
|
|
}
|
|
|
|
template (present) Addr_Union tr_Addr_Union_NameAddr(template (present) NameAddr nameAddr := ?) := {
|
|
nameAddr := nameAddr
|
|
}
|
|
template (value) Addr_Union ts_Addr_Union_NameAddr(template (value) NameAddr nameAddr) := {
|
|
nameAddr := nameAddr
|
|
}
|
|
|
|
template (present) Addr_Union tr_Addr_Union_SipUrl(template (present) SipUrl sipUrl := ?) := {
|
|
addrSpecUnion := sipUrl
|
|
}
|
|
template (value) Addr_Union ts_Addr_Union_SipUrl(template (value) SipUrl sipUrl) := {
|
|
addrSpecUnion := sipUrl
|
|
}
|
|
|
|
|
|
template (present) ContactAddress tr_ContactAddress(template (present) Addr_Union addressField := ?,
|
|
template SemicolonParam_List contactParams := *) := {
|
|
addressField := addressField,
|
|
contactParams := contactParams
|
|
}
|
|
template (value) ContactAddress ts_ContactAddress(template (value) Addr_Union addressField,
|
|
template (omit) SemicolonParam_List contactParams := omit) := {
|
|
addressField := addressField,
|
|
contactParams := contactParams
|
|
}
|
|
|
|
template (present) Contact tr_Contact(template (present) ContactAddress_List contactAddresses := ?) := {
|
|
fieldName := CONTACT_E,
|
|
contactBody := {
|
|
contactAddresses := contactAddresses
|
|
}
|
|
}
|
|
template (value) Contact ts_Contact(template (value) ContactAddress_List contactAddresses) := {
|
|
fieldName := CONTACT_E,
|
|
contactBody := {
|
|
contactAddresses := contactAddresses
|
|
}
|
|
}
|
|
|
|
template (value) Contact ts_ContactWildcard := {
|
|
fieldName := CONTACT_E,
|
|
contactBody := {
|
|
wildcard := "*"
|
|
}
|
|
}
|
|
|
|
template (present) Contact tr_Contact_SipAddr(template (present) SipAddr contact_addr := ?)
|
|
:= tr_Contact({ tr_ContactAddress(contact_addr.addr, contact_addr.params) });
|
|
|
|
private function f_tr_Contact_SipAddr(template SipAddr contact_addr) return template Contact
|
|
{
|
|
if (istemplatekind(contact_addr, "omit")) {
|
|
return omit;
|
|
} else if (istemplatekind(contact_addr, "*")) {
|
|
return *;
|
|
}
|
|
return tr_Contact_SipAddr(contact_addr);
|
|
}
|
|
|
|
template (value) Contact ts_Contact_SipAddr(template (value) SipAddr contact_addr)
|
|
:= ts_Contact({ ts_ContactAddress(contact_addr.addr, contact_addr.params) });
|
|
private function ts_Contact_SipAddr_omit(template (omit) SipAddr contact_addr := omit) return template (omit) Contact
|
|
{
|
|
if (istemplatekind(contact_addr, "omit")) {
|
|
return omit;
|
|
}
|
|
return ts_Contact_SipAddr(contact_addr);
|
|
}
|
|
|
|
|
|
// [20.19]
|
|
template (value) Expires ts_Expires(template (value) DeltaSec deltaSec := "7200") := {
|
|
fieldName := EXPIRES_E,
|
|
deltaSec := deltaSec
|
|
}
|
|
|
|
template (value) SipAddr ts_SipAddr(template (value) HostPort host_port,
|
|
template (omit) UserInfo user_info := omit,
|
|
template (omit) charstring displayName := omit,
|
|
template (omit) SemicolonParam_List params := omit) := {
|
|
addr := {
|
|
nameAddr := {
|
|
displayName := displayName,
|
|
addrSpec := ts_SipUrl(host_port, user_info)
|
|
}
|
|
},
|
|
params := params
|
|
}
|
|
template (present) SipAddr tr_SipAddr(template (present) HostPort host_port := ?,
|
|
template UserInfo user_info := *,
|
|
template charstring displayName := *,
|
|
template SemicolonParam_List params := *) := {
|
|
addr := {
|
|
nameAddr := {
|
|
displayName := displayName,
|
|
addrSpec := tr_SipUrl(host_port, user_info)
|
|
}
|
|
},
|
|
params := params
|
|
}
|
|
|
|
/* build a receive template from a value: substitute '*' for omit */
|
|
function tr_SipAddr_from_val(SipAddr tin) return template (present) SipAddr {
|
|
var template (present) SipAddr ret := tin;
|
|
if (tin.addr.nameAddr.displayName == omit) {
|
|
ret.addr.nameAddr.displayName := *;
|
|
}
|
|
if (tin.addr.nameAddr.addrSpec.userInfo.password == omit) {
|
|
ret.addr.nameAddr.addrSpec.userInfo.password := *;
|
|
}
|
|
if (tin.params == omit) {
|
|
ret.params := *;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
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;
|
|
/* if the port number is 5060, it may be omitted */
|
|
if (isvalue(hp.portField) and valueof(hp.portField) == 5060) {
|
|
hpout.portField := 5060 ifpresent;
|
|
}
|
|
return hpout;
|
|
}
|
|
|
|
|
|
template (value) UserInfo ts_UserInfo(template (value) charstring userOrTelephoneSubscriber,
|
|
template (omit) charstring password := omit) := {
|
|
userOrTelephoneSubscriber := userOrTelephoneSubscriber,
|
|
password := password
|
|
}
|
|
template (present) UserInfo tr_UserInfo(template (present) charstring userOrTelephoneSubscriber := ?,
|
|
template charstring password := *) := {
|
|
userOrTelephoneSubscriber := userOrTelephoneSubscriber,
|
|
password := password
|
|
}
|
|
|
|
template (value) RequestLine ts_SIP_ReqLine(Method method,
|
|
template (value) SipUrl uri,
|
|
charstring ver := c_SIP_VERSION) := {
|
|
method := method,
|
|
requestUri := uri,
|
|
sipVersion := ver
|
|
}
|
|
template (present) RequestLine tr_SIP_ReqLine(template (present) Method method := ?,
|
|
template (present) SipUrl uri := ?,
|
|
template (present) charstring ver := c_SIP_VERSION) := {
|
|
method := method,
|
|
requestUri := uri,
|
|
sipVersion := ver
|
|
}
|
|
|
|
template (value) StatusLine ts_SIP_StatusLine(integer status_code, charstring reason) := {
|
|
sipVersion := "SIP/2.0",
|
|
statusCode := status_code,
|
|
reasonPhrase := reason
|
|
}
|
|
template (present) StatusLine tr_SIP_StatusLine(template integer status_code,
|
|
template charstring reason) := {
|
|
sipVersion := "SIP/2.0",
|
|
statusCode := status_code,
|
|
reasonPhrase := reason
|
|
}
|
|
|
|
|
|
template (value) PDU_SIP_Request ts_SIP_req(template (value) RequestLine rl) := {
|
|
requestLine := rl,
|
|
msgHeader := c_SIP_msgHeader_empty,
|
|
messageBody := omit,
|
|
payload := omit
|
|
}
|
|
|
|
const Method_List c_SIP_defaultMethods := {
|
|
"INVITE", "ACK", "BYE", "CANCEL", "OPTIONS", "PRACK", "MESSAGE", "SUBSCRIBE",
|
|
"NOTIFY", "REFER", "UPDATE" };
|
|
|
|
private function f_ContentTypeOrOmit(template (omit) ContentType ct, template (omit) charstring body)
|
|
return template (omit) ContentType {
|
|
/* if user explicitly stated no content type */
|
|
if (istemplatekind(ct, "omit")) {
|
|
return omit;
|
|
}
|
|
/* if there's no body, then there's no content-type either */
|
|
if (istemplatekind(body, "omit")) {
|
|
return omit;
|
|
}
|
|
return ct;
|
|
}
|
|
|
|
template (value) ContentType ts_CT_SDP := {
|
|
fieldName := CONTENT_TYPE_E,
|
|
mediaType := "application/sdp"
|
|
};
|
|
|
|
template (value) Via ts_Via_from(template (value) HostPort addr) := {
|
|
fieldName := VIA_E,
|
|
viaBody := {
|
|
{
|
|
sentProtocol := { "SIP", "2.0", "UDP" },
|
|
sentBy := addr,
|
|
viaParams := omit
|
|
}
|
|
}
|
|
}
|
|
template (present) Via tr_Via_from(template (present) HostPort host_port := ?,
|
|
template SemicolonParam_List viaParams := *) := {
|
|
fieldName := VIA_E,
|
|
viaBody := {
|
|
{
|
|
sentProtocol := { "SIP", "2.0", "UDP" },
|
|
sentBy := host_port,
|
|
viaParams := viaParams
|
|
}
|
|
}
|
|
}
|
|
|
|
template (value) MessageHeader ts_SIP_msgHeader_empty := c_SIP_msgHeader_empty;
|
|
template (value) MessageHeader
|
|
ts_SIP_msgh_std(template (value) CallidString call_id,
|
|
template (value) SipAddr from_addr,
|
|
template (value) SipAddr to_addr,
|
|
template (omit) Contact contact,
|
|
template (value) charstring method,
|
|
template (value) integer seq_nr,
|
|
template (value) Via via,
|
|
template (omit) ContentType content_type := omit,
|
|
template (value) Method_List allow_methods := c_SIP_defaultMethods,
|
|
template (omit) Expires expires := omit
|
|
) modifies ts_SIP_msgHeader_empty := {
|
|
allow := {
|
|
fieldName := ALLOW_E,
|
|
methods := allow_methods
|
|
},
|
|
callId := {
|
|
fieldName := CALL_ID_E,
|
|
callid := call_id
|
|
},
|
|
contact := contact,
|
|
contentType := content_type,
|
|
cSeq := {
|
|
fieldName := CSEQ_E,
|
|
seqNumber := seq_nr,
|
|
method := method
|
|
},
|
|
expires := expires,
|
|
fromField := {
|
|
fieldName := FROM_E,
|
|
addressField := from_addr.addr,
|
|
fromParams := from_addr.params
|
|
},
|
|
toField := {
|
|
fieldName := TO_E,
|
|
addressField := to_addr.addr,
|
|
toParams := to_addr.params
|
|
},
|
|
userAgent := {
|
|
fieldName := USER_AGENT_E,
|
|
userAgentBody := {
|
|
"osmo-ttcn3-hacks/0.23"
|
|
}
|
|
},
|
|
via := via
|
|
}
|
|
|
|
function tr_AllowMethods(template Method_List allow_methods) return template Allow {
|
|
if (istemplatekind(allow_methods, "omit")) {
|
|
return omit;
|
|
} else if (istemplatekind(allow_methods, "*")) {
|
|
return *;
|
|
} else if (istemplatekind(allow_methods, "?")) {
|
|
return ?;
|
|
}
|
|
var template (present) Allow ret := {
|
|
fieldName := ALLOW_E,
|
|
methods := allow_methods
|
|
}
|
|
return ret
|
|
}
|
|
|
|
template (present) MessageHeader
|
|
tr_SIP_msgh_std(template CallidString call_id,
|
|
template SipAddr from_addr,
|
|
template SipAddr to_addr,
|
|
template Contact contact,
|
|
template (present) Via via := tr_Via_from(?),
|
|
template charstring method,
|
|
template ContentType content_type := *,
|
|
template integer seq_nr := ?,
|
|
template Method_List allow_methods := *,
|
|
template Expires expires := *
|
|
) modifies t_SIP_msgHeader_any := {
|
|
allow := tr_AllowMethods(allow_methods),
|
|
callId := {
|
|
fieldName := CALL_ID_E,
|
|
callid := call_id
|
|
},
|
|
contact := contact,
|
|
contentType := content_type,
|
|
cSeq := {
|
|
fieldName := CSEQ_E,
|
|
seqNumber := seq_nr,
|
|
method := method
|
|
},
|
|
expires := expires,
|
|
fromField := {
|
|
fieldName := FROM_E,
|
|
addressField := from_addr.addr,
|
|
fromParams := from_addr.params
|
|
},
|
|
toField := {
|
|
fieldName := TO_E,
|
|
addressField := to_addr.addr,
|
|
toParams := to_addr.params
|
|
},
|
|
userAgent := *,
|
|
via := via
|
|
}
|
|
|
|
|
|
template (value) PDU_SIP_Request
|
|
ts_SIP_REGISTER(template (value) SipUrl sip_url_host_port,
|
|
template (value) CallidString call_id,
|
|
template (value) SipAddr from_addr,
|
|
template (value) SipAddr to_addr,
|
|
template (value) Via via,
|
|
integer seq_nr,
|
|
template (omit) Contact contact,
|
|
template (omit) Expires expires,
|
|
template (omit) charstring body := omit) := {
|
|
requestLine := ts_SIP_ReqLine(REGISTER_E, sip_url_host_port),
|
|
msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact,
|
|
"REGISTER", seq_nr, via,
|
|
f_ContentTypeOrOmit(ts_CT_SDP, body),
|
|
expires := expires),
|
|
messageBody := body,
|
|
payload := omit
|
|
}
|
|
template (present) PDU_SIP_Request
|
|
tr_SIP_REGISTER(template (present) SipUrl sip_url_host_port := ?,
|
|
template (present) CallidString call_id := ?,
|
|
template (present) SipAddr from_addr := ?,
|
|
template (present) SipAddr to_addr := ?,
|
|
template integer seq_nr := *,
|
|
template Contact contact := *,
|
|
template Expires expires := *,
|
|
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)),
|
|
"INVITE", *, seq_nr,
|
|
expires := expires),
|
|
messageBody := body,
|
|
payload := omit
|
|
}
|
|
|
|
template (value) PDU_SIP_Request
|
|
ts_SIP_INVITE(CallidString call_id,
|
|
SipAddr from_addr,
|
|
SipAddr to_addr,
|
|
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),
|
|
"INVITE", seq_nr,
|
|
ts_Via_from(from_addr.addr.nameAddr.addrSpec.hostPort),
|
|
f_ContentTypeOrOmit(ts_CT_SDP, body)),
|
|
messageBody := body,
|
|
payload := omit
|
|
}
|
|
template (present) PDU_SIP_Request
|
|
tr_SIP_INVITE(template CallidString call_id,
|
|
template SipAddr from_addr,
|
|
template SipAddr to_addr,
|
|
template integer seq_nr,
|
|
template charstring body) := {
|
|
requestLine := tr_SIP_ReqLine(INVITE_E, to_addr.addr.nameAddr.addrSpec),
|
|
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),
|
|
messageBody := body,
|
|
payload := omit
|
|
}
|
|
|
|
template (value) PDU_SIP_Request
|
|
ts_SIP_BYE(CallidString call_id,
|
|
SipAddr from_addr,
|
|
SipAddr to_addr,
|
|
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)),
|
|
messageBody := body,
|
|
payload := omit
|
|
}
|
|
|
|
template (present) PDU_SIP_Request
|
|
tr_SIP_BYE(template CallidString call_id,
|
|
template SipAddr from_addr,
|
|
template SipAddr to_addr,
|
|
template integer seq_nr,
|
|
template charstring body) := {
|
|
requestLine := tr_SIP_ReqLine(BYE_E, to_addr.addr.nameAddr.addrSpec),
|
|
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),
|
|
messageBody := body,
|
|
payload := omit
|
|
}
|
|
|
|
|
|
template (value) PDU_SIP_Request
|
|
ts_SIP_ACK(CallidString call_id,
|
|
SipAddr from_addr,
|
|
SipAddr to_addr,
|
|
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),
|
|
f_ContentTypeOrOmit(ts_CT_SDP, body)),
|
|
messageBody := body,
|
|
payload := omit
|
|
}
|
|
template (present) PDU_SIP_Request
|
|
tr_SIP_ACK(template CallidString call_id,
|
|
template SipAddr from_addr,
|
|
template SipAddr to_addr,
|
|
template integer seq_nr,
|
|
template charstring body) := {
|
|
requestLine := tr_SIP_ReqLine(ACK_E, to_addr.addr.nameAddr.addrSpec),
|
|
msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
|
|
tr_Via_from(tr_HostPort(from_addr.addr.nameAddr.addrSpec.hostPort)),
|
|
"ACK", *, seq_nr),
|
|
messageBody := body,
|
|
payload := omit
|
|
}
|
|
|
|
template (value) PDU_SIP_Response
|
|
ts_SIP_Response(CallidString call_id,
|
|
SipAddr from_addr,
|
|
SipAddr to_addr,
|
|
charstring method,
|
|
integer status_code,
|
|
integer seq_nr,
|
|
charstring reason,
|
|
Via via,
|
|
template (omit) charstring body := omit) := {
|
|
statusLine := ts_SIP_StatusLine(status_code, reason),
|
|
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,
|
|
template SipAddr to_addr,
|
|
template Contact contact,
|
|
template charstring method,
|
|
template integer status_code,
|
|
template integer seq_nr := ?,
|
|
template charstring reason := ?,
|
|
template charstring body := ?) := {
|
|
statusLine := tr_SIP_StatusLine(status_code, reason),
|
|
msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
|
|
tr_Via_from(tr_HostPort(from_addr.addr.nameAddr.addrSpec.hostPort)),
|
|
method, *, seq_nr),
|
|
messageBody := body,
|
|
payload := omit
|
|
}
|
|
|
|
/* Expect during first REGISTER when authorization is required: */
|
|
template (present) PDU_SIP_Response
|
|
tr_SIP_Response_REGISTER_Unauthorized(
|
|
template CallidString call_id,
|
|
template SipAddr from_addr,
|
|
template SipAddr to_addr,
|
|
template (present) Via via := tr_Via_from(?),
|
|
template Contact contact := *,
|
|
template integer seq_nr := ?,
|
|
template charstring method := "REGISTER",
|
|
template integer status_code := 401,
|
|
template charstring reason := "Unauthorized",
|
|
template charstring body := *) := {
|
|
statusLine := tr_SIP_StatusLine(status_code, reason),
|
|
msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
|
|
via,
|
|
method, *, seq_nr),
|
|
messageBody := body,
|
|
payload := omit
|
|
}
|
|
|
|
/* RFC 3261 8.1.1.5:
|
|
* "The sequence number value MUST be expressible as a 32-bit unsigned integer
|
|
* and MUST be less than 2**31."
|
|
*/
|
|
function f_sip_rand_seq_nr() return integer {
|
|
/* 2**31 = 2147483648 */
|
|
return f_rnd_int(2147483648)
|
|
}
|
|
|
|
}
|