| module SIP_Templates { |
| |
| import from SIPmsg_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(charstring user_or_tel, charstring host, integer portnr) := { |
| scheme := "sip", |
| userInfo := { |
| userOrTelephoneSubscriber := user_or_tel, |
| password := omit |
| }, |
| hostPort := { |
| host := host, |
| portField := portnr |
| }, |
| urlParameters := omit, |
| headers := omit |
| } |
| template SipUrl tr_SipUrl(template charstring user_or_tel, |
| template charstring host, |
| template integer portnr) := { |
| scheme := "sip", |
| userInfo := { |
| userOrTelephoneSubscriber := user_or_tel, |
| password := * |
| }, |
| hostPort := { |
| host := host, |
| portField := portnr |
| }, |
| urlParameters := *, |
| headers := * |
| } |
| |
| template (value) SipAddr ts_SipAddr(charstring user_or_tel, charstring host, integer portnr) := { |
| addr := { |
| nameAddr := { |
| displayName := omit, |
| addrSpec := ts_SipUrl(user_or_tel, host, portnr) |
| } |
| }, |
| params := omit |
| } |
| template SipAddr tr_SipAddr(template charstring user_or_tel, |
| template charstring host, |
| template integer portnr) := { |
| addr := { |
| nameAddr := { |
| displayName := *, |
| addrSpec := tr_SipUrl(user_or_tel, host, portnr) |
| } |
| }, |
| params := * |
| } |
| |
| /* build a receive template from a value: substitute '*' for omit */ |
| function tr_SipAddr_from_val(SipAddr tin) return template SipAddr { |
| var template 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; |
| } |
| |
| |
| 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) RequestLine ts_SIP_ReqLine(Method method, template (value) SipUrl uri, |
| charstring ver := c_SIP_VERSION) := { |
| method := method, |
| requestUri := uri, |
| sipVersion := ver |
| } |
| template RequestLine tr_SIP_ReqLine(template Method method, |
| template SipUrl uri, |
| template 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 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(SipAddr from_addr) := { |
| fieldName := VIA_E, |
| viaBody := { |
| { |
| sentProtocol := { "SIP", "2.0", "UDP" }, |
| sentBy := from_addr.addr.nameAddr.addrSpec.hostPort, |
| viaParams := omit |
| } |
| } |
| } |
| |
| template (value) MessageHeader ts_SIP_msgHeader_empty :=c_SIP_msgHeader_empty; |
| template (value) MessageHeader ts_SIP_msgh_std( CallidString call_id, |
| SipAddr from_addr, |
| SipAddr to_addr, |
| template (omit) SipAddr contact_addr, |
| charstring method, |
| integer seq_nr, |
| template (value) Via via, |
| template (omit) ContentType content_type := omit, |
| Method_List allow_methods := c_SIP_defaultMethods |
| ) modifies ts_SIP_msgHeader_empty := { |
| allow := { |
| fieldName := ALLOW_E, |
| methods := allow_methods |
| }, |
| callId := { |
| fieldName := CALL_ID_E, |
| callid := call_id |
| }, |
| contact := ts_Contact(contact_addr), |
| contentType := content_type, |
| cSeq := { |
| fieldName := CSEQ_E, |
| seqNumber := seq_nr, |
| method := method |
| }, |
| 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 |
| } |
| |
| private function tr_Contact(template SipAddr contact_addr) return template Contact |
| { |
| if (istemplatekind(contact_addr, "omit")) { |
| return omit; |
| } else if (istemplatekind(contact_addr, "*")) { |
| return *; |
| } else if (istemplatekind(contact_addr, "?")) { |
| return ?; |
| } |
| var template Contact ret := { |
| fieldName := CONTACT_E, |
| contactBody := { |
| contactAddresses := { |
| { |
| addressField := contact_addr.addr, |
| contactParams := contact_addr.params |
| } |
| } |
| } |
| }; |
| return ret; |
| } |
| |
| private function ts_Contact(template (omit) SipAddr contact_addr) return template (omit) Contact |
| { |
| if (istemplatekind(contact_addr, "omit")) { |
| return omit; |
| } |
| var template (omit) Contact ret := { |
| fieldName := CONTACT_E, |
| contactBody := { |
| contactAddresses := { |
| { |
| addressField := contact_addr.addr, |
| contactParams := contact_addr.params |
| } |
| } |
| } |
| }; |
| return ret; |
| } |
| |
| |
| 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 Allow ret := { |
| fieldName := ALLOW_E, |
| methods := allow_methods |
| } |
| return ret |
| } |
| |
| template MessageHeader tr_SIP_msgh_std( template CallidString call_id, |
| template SipAddr from_addr, |
| template SipAddr to_addr, |
| template SipAddr contact_addr, |
| template charstring method, |
| template ContentType content_type := *, |
| template integer seq_nr := ?, |
| template Method_List allow_methods := * |
| ) modifies t_SIP_msgHeader_any := { |
| allow := tr_AllowMethods(allow_methods), |
| callId := { |
| fieldName := CALL_ID_E, |
| callid := call_id |
| }, |
| contact := tr_Contact(contact_addr), |
| contentType := content_type, |
| cSeq := { |
| fieldName := CSEQ_E, |
| seqNumber := seq_nr, |
| method := method |
| }, |
| 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 := { |
| fieldName := VIA_E, |
| viaBody := { |
| { |
| sentProtocol := { "SIP", "2.0", "UDP" }, |
| sentBy := tr_HostPort(from_addr.addr.nameAddr.addrSpec.hostPort), |
| viaParams := * |
| } |
| } |
| } |
| } |
| |
| |
| template (value) PDU_SIP_Request ts_SIP_INVITE( CallidString call_id, |
| SipAddr from_addr, |
| SipAddr to_addr, |
| integer seq_nr, |
| template (omit) charstring body |
| ) := { |
| requestLine := ts_SIP_ReqLine(INVITE_E, to_addr.addr.nameAddr.addrSpec), |
| msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, from_addr, "INVITE", seq_nr, |
| ts_Via_from(from_addr), f_ContentTypeOrOmit(ts_CT_SDP, body)), |
| messageBody := body, |
| payload := omit |
| } |
| template 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, ?, "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), f_ContentTypeOrOmit(ts_CT_SDP, body)), |
| messageBody := body, |
| payload := omit |
| } |
| |
| template 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, "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, from_addr, "ACK", seq_nr, |
| ts_Via_from(from_addr), f_ContentTypeOrOmit(ts_CT_SDP, body)), |
| messageBody := body, |
| payload := omit |
| } |
| template 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, *, "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 PDU_SIP_Response tr_SIP_Response( template CallidString call_id, |
| template SipAddr from_addr, |
| template SipAddr to_addr, |
| template SipAddr contact_addr, |
| 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_addr, method, *, seq_nr), |
| messageBody := body, |
| payload := omit |
| } |
| |
| |
| |
| } |