/** * @author STF471 * @version $Id$ * @desc This module provides the steps used by the test component for SIP-IMS tests. * This module is part of LibImsV3. */ module LibIms_Steps { // LibSip import from LibSip_SIPTypesAndValues all; import from LibSip_Templates all; import from LibSip_Steps all; import from LibSip_PIXITS all; import from LibSip_Interface all; import from LibSip_MessageBodyTypes all; import from LibSip_Common all; // LibIms import from LibIms_Templates all; import from LibIms_Interface all; import from LibIms_SIPTypesAndValues all; group externalfunctions { } // end group externalfunctions group parameterOperations { /** * @desc Adds new Via parameter * @param p_message (request) SIP message to be used to prepair via header */ function f_addNewViaParameter( in Request p_message ) runs on ImsComponent { var integer v_intVia; var integer i := 0; if (isvalue(p_message.msgHeader.via)) { v_intVia := lengthof(p_message.msgHeader.via.viaBody); while (i < v_intVia) { p_message.msgHeader.via.viaBody[v_intVia] := p_message.msgHeader.via.viaBody[v_intVia - 1]; v_intVia := v_intVia - 1; } vc_branch := c_branchCookie & f_getRndTag(); p_message.msgHeader.via.viaBody[0] := valueof(m_ViaBody_currIpaddr(vc_branch, vc_userprofile)); vc_via := p_message.msgHeader.via; } } /** * @desc Removes own Via parameter * @param p_message (request) SIP message to be used to prepair via header */ function f_removeOwnViaParameter( in Response p_message ) runs on ImsComponent { var integer v_intVia; var Via v_via := c_empty_Via; var integer i := 0; if (ispresent(p_message.msgHeader.via)) { v_intVia := lengthof(p_message.msgHeader.via.viaBody) - 1; for (i := 0; i < v_intVia; i := i + 1) { v_via.viaBody[i] := p_message.msgHeader.via.viaBody[i + 1]; } vc_via := v_via; } } /** * @desc Adds new RecordRoute parameter and removes Route parameter * @param p_message (request) SIP message to be used to prepair via header */ function f_addNewRecordRouteAndRemoveRoutParameter( in Request p_message ) runs on ImsComponent { var integer v_intRoute, v_intRecordRoute; var integer i := 1; var RouteBody v_route1; var Route v_newRoute; v_newRoute.fieldName := ROUTE_E; if (isvalue(p_message.msgHeader.route)) { v_intRoute := lengthof(p_message.msgHeader.route.routeBody); v_route1 := p_message.msgHeader.route.routeBody[0]; while (i < v_intRoute) { v_newRoute.routeBody[i - 1] := p_message.msgHeader.route.routeBody[i]; i := i + 1; } vc_route := v_newRoute; } if (isvalue(p_message.msgHeader.recordRoute)) { v_intRecordRoute := lengthof(p_message.msgHeader.recordRoute.routeBody); while (0 < v_intRecordRoute) { p_message.msgHeader.recordRoute.routeBody[v_intRecordRoute] := p_message.msgHeader.recordRoute.routeBody[v_intRecordRoute - 1]; v_intRecordRoute := v_intRecordRoute - 1; } p_message.msgHeader.recordRoute.routeBody[0] := v_route1; vc_recordRoute := valueof(p_message.msgHeader.recordRoute); } } /** * @desc Adds new RecordRoute parameter (IMS) * @param p_rr The recordRoute parameter to add */ function f_addNewRecordRouteIMS( in RecordRoute p_rr ) runs on ImsComponent return template RecordRoute { var integer v_intRecordRoute; var template RecordRoute v_recordRoute := omit; v_intRecordRoute := lengthof(p_rr.routeBody); if (v_intRecordRoute > 0) { while (0 < v_intRecordRoute) { p_rr.routeBody[v_intRecordRoute] := p_rr.routeBody[v_intRecordRoute - 1]; v_intRecordRoute := v_intRecordRoute - 1; } p_rr.routeBody[0] := valueof(m_routeBody_currIpAddr(vc_userprofile)); vc_recordRoute := p_rr; return vc_recordRoute; } else { return (v_recordRoute); } } } // end group parameterOperations group fieldOperations { /** * @desc Sets BYE header fields (IMS addresses) extension of general settings from LibSip basic function * @param p_cSeq_s The current cSeq * @param p_to_user The selected user's SIP URL */ function f_setHeadersBYE( inout CSeq p_cSeq_s, in SipUrl p_to_user ) runs on ImsComponent { vc_requestUri := p_to_user; // Request URI of Invite is identical with To header vc_route := f_route(); // update the route header field depending on vc_boo_route vc_recordRoute := f_recordroute(); // update the route header field depending on vc_boo_route LibSip_Steps.f_setHeadersBYE(p_cSeq_s); } // end f_setHeadersBYE /** * @desc Sets CANCEL header fields (IMS addresses) extension of general settings from LibSip basic function * @param p_cSeq_s The current cSeq */ function f_setHeadersCANCEL( inout CSeq p_cSeq_s ) runs on ImsComponent { vc_route := f_route(); // update the route header field depending on vc_boo_route vc_recordRoute := f_recordroute(); // update the route header field depending on vc_boo_route LibSip_Steps.f_setHeadersCANCEL(p_cSeq_s); } // end f_setHeadersCANCEL /** * @desc Sets headers for forward request from AS in case if AS acts as Proxy * @param p_cSeq_s The current cSeq * @param p_proxyMode true = proxyMode, false = B2BMode */ function f_setHeadersForwardRequestFromAS( inout CSeq p_cSeq_s, boolean p_proxyMode ) runs on ImsComponent { var Request v_request; v_request := vc_request; if (p_proxyMode) { vc_requestUri2 := v_request.requestLine.requestUri; vc_to := v_request.msgHeader.toField; vc_contact := v_request.msgHeader.contact; f_addNewViaParameter(v_request); f_addNewRecordRouteAndRemoveRoutParameter(v_request); } else { // B2Bmode vc_contact := m_Contact(m_SipUrl_contactIpaddr(vc_userprofile)); if (PX_SEED) { vc_callId := { fieldName := CALL_ID_E, callid := f_getRndCallId() }; } else { vc_callId := { fieldName := CALL_ID_E, callid := f_getRndCallId() & c_AT & vc_userprofile.currIpaddr }; } } } // end function f_setHeadersForwardRequest /** * @desc Sets header fields for forward request from AS in case if AS acts as Proxy */ function f_setHeadersForwardResponseFromAS( ) runs on ImsComponent { var Response v_response; v_response := vc_response; vc_caller_To := v_response.msgHeader.toField; vc_to := v_response.msgHeader.toField; vc_contact := v_response.msgHeader.contact; if (ispresent(v_response.msgHeader.recordRoute)) { vc_recordRoute := v_response.msgHeader.recordRoute; } f_removeOwnViaParameter(v_response); } // end function f_setHeadersForwardResponse /** * @desc Sets Invite header fields (IMS addresses) extension of general settings from LibSip basic function * @param p_cSeq_s The current cSeq * @param p_to_user The selected user's SIP URL */ function f_setHeadersINVITE( inout CSeq p_cSeq_s, in SipUrl p_to_user, in SipUrl p_from_user ) runs on ImsComponent { vc_to := f_initToHeader(p_to_user); // init of vc_to using userProfile identifier vc_from := f_initFromHeader(p_from_user, f_getRndTag()); // init of vc_from using userProfile identifier vc_requestUri := p_to_user; // Request URI of Invite is identical with To header if (vc_boo_route) { vc_route := m_route_interface(vc_interfaceprofile); } if (vc_boo_recordRoute) { vc_recordRoute := m_recordRoute_currIpAddr(vc_userprofile); } LibSip_Steps.f_setHeadersINVITE(p_cSeq_s); } // end f_setHeadersINVITE /** * @desc Sets Invite header fields (IMS addresses) extension of general settings from LibSip basic function * @param p_cSeq_s The current cSeq * @param p_to_user The selected user's SIP URL */ function f_setHeadersUPDATE( inout CSeq p_cSeq_s, in SipUrl p_to_user, in SipUrl p_from_user ) runs on ImsComponent { vc_to := f_initToHeader(p_to_user); // init of vc_to using userProfile identifier vc_from := f_initFromHeader(p_from_user, f_getRndTag()); // init of vc_from using userProfile identifier vc_requestUri := p_to_user; // Request URI of Invite is identical with To header if (vc_boo_route) { vc_route := m_route_interface(vc_interfaceprofile); } if (vc_boo_recordRoute) { vc_recordRoute := m_recordRoute_currIpAddr(vc_userprofile); } LibSip_Steps.f_setHeadersUPDATE(p_cSeq_s); } // end f_setHeadersUPDATE /** * @desc Sets Message header fields (IMS addresses) extension of general settings from LibSip basic function * @param p_cSeq_s The current cSeq * @param p_to_user The selected user's SIP URL */ function f_setHeadersMESSAGE( inout CSeq p_cSeq_s, in SipUrl p_to_user, in SipUrl p_from_user ) runs on ImsComponent { vc_to := f_initToHeader(p_to_user); // init of vc_to using userProfile identifier vc_from := f_initFromHeader(p_from_user, f_getRndTag()); // init of vc_from using userProfile identifier vc_requestUri := p_to_user; // Request URI of Invite is identical with To header LibSip_Steps.f_setHeadersMESSAGE(p_cSeq_s); } // end f_setHeadersMESSAGE /** * @desc Sets Notify header fields (IMS addresses) extension of general settings from LibSip basic function * @param p_cSeq_s The current cSeq * @param p_to_user The selected user's SIP URL */ function f_setHeadersNOTIFY( inout CSeq p_cSeq_s, in SipUrl p_to_user, in SipUrl p_from_user ) runs on ImsComponent { LibSip_Steps.f_setHeadersNOTIFY(p_cSeq_s); vc_branch := c_branchCookie & f_getRndTag(); vc_via := { fieldName := VIA_E, viaBody := {valueof(m_ViaBody_virtual_XCSCF(vc_branch, vc_userprofile))} }; vc_to := f_initToHeader(p_to_user); // init of vc_to using userProfile identifier vc_from := f_initFromHeader(p_from_user, f_getRndTag()); // init of vc_from using userProfile identifier vc_requestUri := p_to_user; // Request URI of Invite is identical with To header // contact header initialization for sending of NOTIFY from CSCF component vc_contact := m_Contact(m_SipUrl_currIpaddr_CSCF(vc_userprofile)); } // end f_setHeadersNOTIFY /** * @desc Sets Publish header fields (IMS addresses) extension of general settings from LibSip basic function * @param p_cSeq_s The current cSeq * @param p_to_user The selected user's SIP URL */ function f_setHeadersPUBLISH( inout CSeq p_cSeq_s, in SipUrl p_to_user, in SipUrl p_from_user ) runs on ImsComponent { LibSip_Steps.f_setHeadersPUBLISH(p_cSeq_s); vc_branch := c_branchCookie & f_getRndTag(); vc_via := { fieldName := VIA_E, viaBody := {valueof(m_ViaBody_virtual_XCSCF(vc_branch, vc_userprofile))} }; vc_to := f_initToHeader(p_to_user); // init of vc_to using userProfile identifier vc_from := f_initFromHeader(p_from_user, f_getRndTag()); // init of vc_from using userProfile identifier vc_requestUri := p_to_user; // Request URI of Invite is identical with To header if (vc_boo_route) { vc_route := m_route_interface(vc_interfaceprofile); } if (vc_boo_recordRoute) { vc_recordRoute := m_recordRoute_currIpAddr(vc_userprofile); } // contact header initialization for sending of PUBLISH from CSCF component vc_contact := m_Contact(m_SipUrl_currIpaddr_CSCF(vc_userprofile)); } // end f_setHeadersPUBLISH /** * @desc Sets Subscribe header fields (IMS addresses) extension of general settings from LibSip basic function * @param p_cSeq_s The current cSeq * @param p_to_user The selected user's SIP URL */ function f_setHeadersSUBSCRIBE( inout CSeq p_cSeq_s, in SipUrl p_to_user, in SipUrl p_from_user ) runs on ImsComponent { vc_to := { fieldName := TO_E, addressField := { nameAddr := { displayName := omit, // optional charstring addrSpec := p_to_user // SipUrl } }, // end addressField toParams := omit }; vc_from := f_initFromHeader(p_from_user, f_getRndTag()); // init of vc_from using userProfile identifier vc_requestUri := p_to_user; // Request URI of Invite is identical with To header LibSip_Steps.f_setHeadersSUBSCRIBE(p_cSeq_s); } // end f_setHeadersSUBSCRIBE /** * @desc Sets headers for ReINVITE method * @param p_cSeq_s The current cSeq * @param p_orginatingSide true in case of Re-INVITE is send from the orgination endpoint otherwise false. * @param p_to_user The selected user's SIP URL */ function f_setHeadersReINVITE( inout CSeq p_cSeq_s, in boolean p_orginatingSide, in SipUrl p_to_user ) runs on ImsComponent { var integer v_tmp, i, j, v_nbroute; var Request v_request; v_request := vc_request; f_setHeadersGeneral(p_cSeq_s, "INVITE"); // cseq, contact, branch, via vc_reqHostPort := vc_requestUri.components.sip.hostPort; vc_requestUri := p_to_user; if (p_orginatingSide) { vc_to := vc_caller_To; vc_from := vc_caller_From; } else { vc_to := vc_callee_To; vc_from := vc_callee_From; // get route from previous ACK request // Route Management if (isvalue(v_request.msgHeader.recordRoute)) { vc_recordRoute := valueof(v_request.msgHeader.recordRoute); v_nbroute := lengthof(vc_recordRoute.routeBody); // copy and reverse the order of the routes in route header for (i := 0; i <= (v_nbroute - 1); i := i + 1) { j := v_nbroute - 1 - i; vc_route.routeBody[j] := vc_recordRoute.routeBody[i]; } vc_route.fieldName := ROUTE_E; vc_boo_recordRoute := true; vc_boo_route := true; } else { vc_boo_recordRoute := false; vc_boo_route := false; } } v_tmp := str2int(vc_sdp_local.origin.session_id); vc_sdp_local.origin.session_id := int2str(v_tmp + 1); v_tmp := str2int(vc_sdp_local.origin.session_version); vc_sdp_local.origin.session_version := int2str(v_tmp + 1); } // end function f_setHeadersReINVITE /** * @desc Sets component variables related to message header fields when sending requests from the home I-CSCF (TS) to the visited P-CSCF (SUT) (message type independent: CSeq, contact, via), function uses information from userprofile and interfaceprofile * @param p_cSeq_s The CSeq parameter * @param p_method The method name for cSeq header field */ function f_setHeadersGeneral_ICSCF( inout CSeq p_cSeq_s, in charstring p_method ) runs on SipComponent { p_cSeq_s.fieldName := CSEQ_E; p_cSeq_s.seqNumber := p_cSeq_s.seqNumber + 1; p_cSeq_s.method := p_method; vc_cSeq := p_cSeq_s; vc_contact := m_Contact(m_SipUrl_contactIpaddr(vc_userprofile)); vc_branch := c_branchCookie & f_getRndTag(); vc_branch_ICSCF := c_branchCookie & f_getRndTag(); vc_via := { fieldName := VIA_E, viaBody := { valueof(m_ViaBody_currIpaddr(vc_branch, vc_userprofile)), valueof(m_ViaBody_virtualUEinPCSCF(vc_branch_ICSCF, vc_userprofile)) } }; } // end function f_setHeadersGeneral_ICSCF /** * @desc Sets header field for the next outgoing REGISTER message from the visited P-CSCF to the home I-CSCF * @param p_cSeq_s The CSeq parameter to be applied */ function f_setHeaders_REGISTER_PCSCF( inout CSeq p_cSeq_s ) runs on SipComponent { var SemicolonParam_List v_params; f_setHeadersGeneral(p_cSeq_s, "REGISTER"); // cseq, contact, branch, via vc_requestUri := { scheme := c_sipScheme, components := { sip := { userInfo := omit, hostPort := { host := vc_userprofile.registrarDomain, portField := omit } } }, urlParameters := omit, headers := omit }; vc_reqHostPort := vc_requestUri.components.sip.hostPort; if (PX_SEED) { vc_callId := { fieldName := CALL_ID_E, callid := f_getRndCallId() }; } else { vc_callId := { fieldName := CALL_ID_E, callid := f_getRndCallId() & c_AT & vc_userprofile.currIpaddr }; } vc_callIdReg := vc_callId; vc_to := valueof(m_To(m_SipUrl_currDomain(vc_userprofile))); v_params := { { id := c_tagId, paramValue := { tokenOrHost := f_getRndTag() } } }; vc_from := { fieldName := FROM_E, addressField := vc_to.addressField, fromParams := v_params }; if (not vc_firstREGISTER_sent) { v_params := { { id := c_expiresId, paramValue := { tokenOrHost := c_shortRegistration } } }; vc_contact.contactBody.contactAddresses[0].contactParams := v_params; } vc_firstREGISTER_sent := true; // f_setHeaders_Register is called in deREGISTER function vc_authorization := { fieldName := AUTHORIZATION_E, body := {f_calculatecCredentials_empty(vc_userprofile)} }; } // end function setHeaders_REGISTER_PCSCF /** * @desc Sets REFER header fields (IMS addresses) extension of general settings from LibSip basic function * @param p_cSeq_s The current cSeq * @param p_to_user The selected user's SIP URL */ function f_setHeadersREFER( inout CSeq p_cSeq_s, in SipUrl p_to_user ) runs on ImsComponent { vc_requestUri := p_to_user; // Request URI of Invite is identical with To header if (vc_boo_route) { vc_route := m_route_interface(vc_interfaceprofile); } if (vc_boo_recordRoute) { vc_recordRoute := m_recordRoute_currIpAddr(vc_userprofile); } LibSip_Steps.f_setHeadersREFER(p_cSeq_s); } // end f_setHeadersREFER /** * @desc Sets REFER header fields (IMS addresses) extension of general settings from LibSip basic function * @param p_cSeq_s The current cSeq * @param p_uri The SipUrl for request URI and To header */ function f_setHeadersREFER_conf( inout CSeq p_cSeq_s, in SipUrl p_uri ) runs on ImsComponent { vc_to := { fieldName := TO_E, addressField := { nameAddr := { displayName := omit, // optional charstring addrSpec := p_uri // SipUrl } }, // end addressField toParams := omit }; vc_from := f_initFromHeader(p_uri, f_getRndTag()); // init of vc_from using userProfile identifier vc_requestUri := p_uri; // Request URI of Invite is identical with To header if (vc_boo_route) { vc_route := m_route_interface(vc_interfaceprofile); } if (vc_boo_recordRoute) { vc_recordRoute := m_recordRoute_currIpAddr(vc_userprofile); } LibSip_Steps.f_setHeadersREFER(p_cSeq_s); } // end f_setHeadersREFER_conf } // end group fieldOperations group awaitingMessage { } group sendMessage { /** * @desc Sends PRACK message * @param p_mb The message body of the PRACK message * @param p_rack_cseq The cSeq of the PRACK message */ function f_sendPRACK_sdp( template(value) MessageBody p_mb, CSeq p_rack_cseq ) runs on SipComponent { var integer v_responseNum := 1; var template(value) PRACK_Request v_prackReq; f_setHeadersGeneral(vc_cSeq, "PRACK"); // cseq, contact, branch, via if (isvalue(vc_response.msgHeader.rSeq.responseNum)) { v_responseNum := vc_response.msgHeader.rSeq.responseNum; } vc_rAck := m_RAck(v_responseNum, p_rack_cseq.seqNumber, p_rack_cseq.method); v_prackReq := m_PRACK_Request_sdp(vc_requestUri, vc_callId, vc_cSeq, vc_from, vc_to, vc_via, vc_rAck, p_mb); // added route header if required if (isvalue(vc_response.msgHeader.recordRoute)) { v_prackReq.msgHeader.route := f_route(); } SIPP.send(v_prackReq) to vc_sent_label; } } group globalSteps { //NOTE STF471: removed function f_init_userprofile, have to move up to specific ATS /** * @desc Initializes the To header * @param p_user Identifies the selected user's SIP URL * @return The To header */ function f_initToHeader( in SipUrl p_user ) runs on ImsComponent return To { var To v_to := c_empty_To; v_to := { fieldName := TO_E, addressField := { nameAddr := { displayName := omit, // optional charstring addrSpec := p_user // SipUrl } }, // end addressField toParams := omit }; return (v_to); } /** * @desc Initializes the From header * @param p_user Identifies the selected user' SIP URL * @param p_tag_str The string value of the tag id * @return The From header */ function f_initFromHeader( in SipUrl p_user, charstring p_tag_str ) runs on ImsComponent return From { var From v_from := c_empty_From; v_from := { fieldName := FROM_E, addressField := { nameAddr := { displayName := omit, // optional charstring addrSpec := p_user // SipUrl } }, // end addressField fromParams := { { id := c_tagId, paramValue := { tokenOrHost := p_tag_str } } } }; return v_from; } //NOTE STF471: removed function f_initSipUrl, have to move up to specific ATS //NOTE STF471: removed function f_init_interfaceprofile, have to move up to specific ATS /** * @desc Retrieves user DomainPort value of the user profile * @param p_userProfile Identifies the selected user profile * @return The Domain HostPort */ function f_get_userDomainPort( in SipUserProfile p_userProfile ) runs on ImsComponent return HostPort { return { p_userProfile.homeDomain, p_userProfile.currPort }; } /** * @desc Retrieves HostPort value of the interface profile * @param p_interface Identifies the selected interface * @return The HostPort */ function f_get_interfaceHostPort( in ImsInterfaceProfile p_interface ) runs on ImsComponent return HostPort { return { p_interface.SUTIpaddr, p_interface.SUTPort }; } /** * @desc Retrieves DomainPort value of the interface profile * @param p_interface Identifies the selected interface * @return The Domain HostPort */ function f_get_interfaceDomainPort( in ImsInterfaceProfile p_interface ) runs on ImsComponent return HostPort { return { p_interface.SUTHomeDomain, p_interface.SUTPort }; } /** * @desc Gets the receive template for the NameAddr of the interface * @param p_interface Identifies the selected interface * @return The NameAddr template */ function f_get_interfaceNameAddr( in ImsInterfaceProfile p_interface ) runs on ImsComponent return template NameAddr { return mw_SipUrl_SUTinterface(p_interface.SUTIpaddr, p_interface.SUTPort); } } group registration { /** * @desc Registration and authentication * @param p_cSeq_s The current cseq * @param p_auth flag indicating if authentication is needed * @param p_host P-CSCF domain name (formerly value from module parameter PX_IMS_TS_PCSCF_HOME_DOMAIN) * @param p_port P-CSCF port number (formerly value from module parameter PX_IMS_TS_PCSCF_PORT) */ function f_Registration_IMS( inout CSeq p_cSeq_s, in boolean p_auth, template(value) charstring p_host, template(value) integer p_port ) runs on SipComponent { f_setHeaders_REGISTER(p_cSeq_s); f_SendREGISTER(m_REGISTER_Request_IMS(vc_requestUri, vc_callId, vc_cSeq, vc_from, vc_to, vc_via_REG, vc_contact, m_add_Authorization_digest(vc_authorization, {c_Integrity_protected_no}), p_host, p_port)); // LibSip // awaiting of 401 and sending 2nd REGISTER and awaiting 200 OK REGISTER if (p_auth) { // receiving 401 Unauthorized response. // and Re-send REGISTER request with Authorization header tc_ack.start; alt { [] SIPP.receive(mw_Response_Base(c_statusLine401, vc_callId, p_cSeq_s)) -> value vc_response { tc_ack.stop; // set headers via, cseq and authorization f_setHeaders_2ndREGISTER(p_cSeq_s); f_SendREGISTER(m_REGISTER_Request_IMS(vc_requestUri, vc_callId, vc_cSeq, vc_from, vc_to, vc_via_REG, vc_contact, m_add_Authorization_digest(vc_authorization, {c_Integrity_protected_yes}), p_host, p_port)); // LibSip // awaiting 200 OK REGISTER f_awaitingOkResponse(p_cSeq_s); f_getServiceRouteMapIntoRouteInRegistration(vc_response); } [] SIPP.receive(mw_Response_Base(c_statusLine200, vc_callId, p_cSeq_s)) { tc_ack.stop; log("*** " & __SCOPE__ & ": INCONC: Authorization was not requested as expected ***"); setverdict(inconc); } } } else { f_awaitingOkResponse(p_cSeq_s); f_getServiceRouteMapIntoRouteInRegistration(vc_response); } } // end function f_Registration_IMS /** * @desc awaiting UE1 registration (with authentication) * @param p_cSeq_s The current cseq * @param p_to_user The selected user's SIP URL * @param p_qop of the peer UE (alternatively) * @param p_register The expected REGISTER_Request - default: mw_REGISTER_authorizedRequest_IMS */ function f_awaitingRegistration_IMS( inout CSeq p_cSeq_s, in SipUrl p_to_user, in charstring p_qop, in template(present) REGISTER_Request p_register := mw_REGISTER_authorizedRequest_IMS( mw_Authorization_digest( mw_digestResponse( (c_Integrity_protected_yes, c_Integrity_protected_ip_assoc_pending) ) ) ) ) runs on ImsComponent { var SipUrl v_passociated_url; // Awaiting 1st REGISTER f_awaitingREGISTER(mw_REGISTER_unauthorizedRequest_IMS); // 401 response f_sendResponse( m_Response_WWWauthenticate_IMS( c_statusLine401, vc_callId, p_cSeq_s, vc_caller_From, vc_caller_To, vc_via, m_wwwAuthenticate( f_calculatecChallenge_forWWWAuthorization( p_qop, valueof(vc_authorization.body[0].digestResponse) ) ) ) ); // Awaiting 2nd REGISTER with authorization header f_awaitingREGISTER(p_register); // 200OK to complete the request if (isvalue(vc_request.msgHeader.contact)) { vc_contact := valueof(vc_request.msgHeader.contact); vc_contact.contactBody.contactAddresses[0].contactParams := { { "expires", { tokenOrHost := int2str(3600) } } }; } v_passociated_url := vc_caller_From.addressField.nameAddr.addrSpec; f_sendResponse(m_Response_2xxonREGISTER_IMS(c_statusLine200, vc_callId, p_cSeq_s, vc_callee_From, vc_callee_To, vc_via, vc_contact, p_to_user, v_passociated_url)); } // end function f_awaitingRegistration_IMS /** * @desc Awaiting UE1 registration (with authentication, without security headers) * @param p_cSeq_s The current cseq * @param p_to_user The selected user's SIP URL * @param p_qop of the peer UE (alternatively) */ function f_awaitingRegistration_IMS_gm( inout CSeq p_cSeq_s, in SipUrl p_to_user, in charstring p_qop ) runs on ImsComponent { vc_ignore_subscribe := true; // handle SUBSCRIBE during the call f_awaitingRegistration_IMS(p_cSeq_s, p_to_user, p_qop, mw_REGISTER_authorizedRequest_wo_securityheaders_IMS); vc_DeregDone := false; } // end function f_awaitingRegistration_IMS_gm /** * @desc Remove registration * @param p_cSeq_s The current cseq * @param p_host P-CSCF domain name (formerly value from module parameter PX_IMS_TS_PCSCF_HOME_DOMAIN) * @param p_port P-CSCF port number (formerly value from module parameter PX_IMS_TS_PCSCF_PORT) */ function f_removeRegistration_IMS( inout CSeq p_cSeq_s, template(value) charstring p_host, template(value) integer p_port ) runs on SipComponent { var template(value) REGISTER_Request v_request; if (PX_SIP_REGISTRATION) { f_setHeaders_deREGISTER(p_cSeq_s); v_request := m_REGISTER_Request_expires_IMS(vc_requestUri, vc_callIdReg, p_cSeq_s, vc_from, vc_to, vc_via, vc_contact, vc_authorization, p_host, p_port, "0"); v_request.msgHeader.route := f_route(); f_SendREGISTER(v_request); if (PX_SIP_REGISTER_AUTHENTICATION_ENABLED) { // receiving 401 Unauthorized response. // and Re-send REGISTER request with Authorization header tc_ack.start; alt { [] SIPP.receive(mw_Response_Base(c_statusLine401, vc_callIdReg, p_cSeq_s)) -> value vc_response { tc_ack.stop; // set headers via, cseq and authorization f_setHeaders_2ndREGISTER(p_cSeq_s); v_request := m_REGISTER_Request_expires_IMS(vc_requestUri, vc_callIdReg, p_cSeq_s, vc_from, vc_to, vc_via, vc_contact, vc_authorization, p_host, p_port, "0"); v_request.msgHeader.route := f_route(); // Re-send protected REGISTER f_SendREGISTER(v_request); // LibSip // awaiting 200 OK REGISTER f_awaitingResponse(mw_Response_Base(c_statusLine200, vc_callIdReg, p_cSeq_s)); } [] SIPP.receive(mw_Response_Base(c_statusLine200, vc_callIdReg, p_cSeq_s)) -> value vc_response { tc_ack.stop; f_setHeadersOnReceiptOfResponse(vc_response); log("*** " & __SCOPE__ & ": INFO: Authorization was not requested as expected ***"); } } } else { f_awaitingResponse(mw_Response_Base(c_statusLine200, vc_callIdReg, p_cSeq_s)); } } } // end f_RemoveRegistration_IMS } // end group registration group preambles { /** * @desc Sets variables and default initialization for user profile where proxy role is present * @param p_userprofile User profile of call * @param p_cSeq_s The current cseq */ function f_IMS_preamble_MGCF( inout CSeq p_cSeq_s ) runs on ImsComponent { vc_boo_recordRoute := true; vc_boo_route := true; //NOTE STF471: removed f_init_interfaceprofile(c_interfaceProfile_IMS_SUT_MGCF); f_IMS_preamble_woRegistration(p_cSeq_s); } /** * @desc Sets variables and default initialization for user profile * @param p_cSeq_s The current cseq */ function f_IMS_preamble_woRegistration( inout CSeq p_cSeq_s ) runs on ImsComponent { // avoid deregistration in default behavior vc_DeregDone := true; vc_boo_route := true; vc_boo_recordRoute := true; // Variables & defaults initialization LibSip_Steps.f_init_component(p_cSeq_s); // Preamble //NOTE STF471: removed f_init_userprofile(p_userprofile); // assignment of PIXIT values to component variable vc_sdp_local := valueof(m_SDP_bandwidth(m_media_dynPT(PX_SIP_SDP_DYN, PX_SIP_SDP_ENCODING, PX_SIP_SDP_CLOCKRATE, omit), vc_userprofile)); vc_contact := m_Contact(m_SipUrl_contactIpaddr(vc_userprofile)); } //NOTE STF471 added /** * @desc Sets variables and default initialization for user profile * @param p_cSeq_s The current cseq */ function f_IMS_preamble_woRegistration_as( inout CSeq p_cSeq_s ) runs on ImsComponent { // avoid deregistration in default behavior vc_DeregDone := true; vc_boo_route := true; vc_boo_recordRoute := true; // Variables & defaults initialization LibSip_Steps.f_init_component(p_cSeq_s); // Preamble //NOTE STF471: removed f_init_userprofile(p_userprofile); // assignment of PIXIT values to component variable vc_sdp_local := valueof(m_SDP_bandwidth(m_media_dynPT(PX_SIP_SDP_DYN, PX_SIP_SDP_ENCODING, PX_SIP_SDP_CLOCKRATE, omit), vc_userprofile)); } /** * @desc Sets variables and default initialization for user profile and handle registration and authentication with MD5 * @param p_cSeq_s The current cseq * @param p_register Register template */ function f_IMS_preamble_withEmergencyRegistration( inout CSeq p_cSeq_s, template REGISTER_Request p_register ) runs on ImsComponent { //NOTE STF471: removed f_init_interfaceprofile(p_interface); // Variables & defaults initialization f_IMS_preamble_woRegistration(p_cSeq_s); // Preamble f_Registration(p_cSeq_s, p_register, PX_SIP_REGISTER_AUTHENTICATION_ENABLED, true); // deregistration in case of successful registration vc_DeregDone := false; } /** * @desc Sets variables and default initialization for user profile and handle registration and authentication with MD5 * @param p_cSeq_s The current cseq * @param p_register Register template */ function f_IMS_preamble_withRegistration( inout CSeq p_cSeq_s, out template REGISTER_Request p_register ) runs on ImsComponent { //NOTE STF471: removed f_init_interfaceprofile(p_interface); // Variables & defaults initialization f_IMS_preamble_woRegistration(p_cSeq_s); // Preamble f_Registration(p_cSeq_s, p_register, PX_SIP_REGISTER_AUTHENTICATION_ENABLED); // deregistration in case of successful registration vc_DeregDone := false; f_setHeaders_SUBSCRIBE(p_cSeq_s); f_Subscription(p_cSeq_s, m_SUBSCRIBE_Request_UE(vc_requestUri, vc_callId, p_cSeq_s, vc_from, vc_to, vc_via, vc_contact, vc_route_REG)); } //NOTE STF471 added /** * @desc Sets variables and default initialization for user profile and handle registration and authentication with MD5 * @param p_cSeq_s The current cseq * @param p_register Register template */ function f_IMS_preamble_withRegistrationWoSubscription( inout CSeq p_cSeq_s, out template REGISTER_Request p_register ) runs on ImsComponent { //NOTE STF471: removed f_init_interfaceprofile(p_interface); // Variables & defaults initialization f_IMS_preamble_woRegistration(p_cSeq_s); // Preamble f_Registration(p_cSeq_s, p_register, PX_SIP_REGISTER_AUTHENTICATION_ENABLED); // deregistration in case of successful registration vc_DeregDone := false; } /** * @desc Sets variables and default initialization for user profile and handle registration and authentication with MD5 (basic registration template) * @param p_cSeq_s The current cseq * @param p_host P-CSCF domain name (formerly value from module parameter PX_IMS_TS_PCSCF_HOME_DOMAIN) * @param p_port P-CSCF port number (formerly value from module parameter PX_IMS_TS_PCSCF_PORT) */ function f_IMS_preamble_withRegistrationBasic( inout CSeq p_cSeq_s, template(value) charstring p_host, template(value) integer p_port ) runs on ImsComponent { //NOTE STF471: removed f_init_interfaceprofile(p_interface); // Variables & defaults initialization f_IMS_preamble_woRegistration(p_cSeq_s); // Preamble f_Registration_IMS(p_cSeq_s, PX_SIP_REGISTER_AUTHENTICATION_ENABLED, p_host, p_port); f_setHeaders_SUBSCRIBE(p_cSeq_s); f_Subscription(p_cSeq_s, m_SUBSCRIBE_Request_UE(vc_requestUri, vc_callId, p_cSeq_s, vc_from, vc_to, vc_via, vc_contact, vc_route_REG)); } /** * @desc Sets variables and default initialization for user profile and handle registration and authentication with MD5 (basic registration template) * @param p_cSeq_s The current cseq */ function f_IMS_preamble_AS( inout CSeq p_cSeq_s ) runs on ImsComponent { // avoid deregistration in default behavior vc_DeregDone := true; vc_boo_route := true; vc_boo_recordRoute := true; vc_cSeq := p_cSeq_s; // Defaults vc_def_catchSyncStop := activate(a_Sip_catchSyncStop()); vc_default := activate(a_altstep_AS()); // Preamble //NOTE STF471: removed f_init_interfaceprofile(p_interface); //NOTE STF471: removed f_init_userprofile(p_userprofile); // assignment of PIXIT values to component variable vc_sdp_local := valueof(m_SDP_bandwidth(m_media_dynPT(PX_SIP_SDP_DYN, PX_SIP_SDP_ENCODING, PX_SIP_SDP_CLOCKRATE, omit), vc_userprofile)); vc_contact := m_Contact(m_SipUrl_contactIpaddr(vc_userprofile)); } } // end group preambles group postambles { /** * @desc Terminates component and handles deregistration * @param p_cSeq_s The current cseq */ function f_IMS_postamble_withDeRegistration( CSeq p_cSeq_s ) runs on ImsComponent { f_RemoveRegistration(p_cSeq_s); f_terminate_component(); } /** * @desc Terminates component and optionally handles deregistration on AS as TS * @param p_deRegistration Handle deregistration? */ function f_IMS_postamble_AS_withDeRegistration( boolean p_deRegistration ) runs on ImsComponent { if (p_deRegistration == true) { f_awaitingREGISTER_sendReply(mw_REGISTER_Request_Base, true); } f_terminate_component(); } /** * @desc Terminates component without registration */ function f_SIP_postamble_IMS1_withoutRegistration( ) runs on ImsComponent { f_terminate_component(); } /** * @desc Terminates component without de-registration */ function f_IMS_postamble_withoutDeRegistration( ) runs on ImsComponent { f_terminate_component(); } /** * @desc Terminates component with de-registration * @param p_to_user The selected user's SIP URL * @param p_qop of the peer UE (alternatively) */ function f_SIP_postamble_IMS1_awaitDeRegistration( in SipUrl p_to_user, in charstring p_qop ) runs on ImsComponent { var SipUrl v_passociated_url; // Awaiting 1st REGISTER f_awaitingREGISTER(mw_REGISTER_unauthorizedRequest_IMS); // 401 response f_sendResponse(m_Response_WWWauthenticate_IMS(c_statusLine401, vc_callId, vc_cSeq, vc_caller_From, vc_caller_To, vc_via, m_wwwAuthenticate(f_calculatecChallenge_forWWWAuthorization(p_qop, valueof(vc_authorization.body[0].digestResponse))))); // Awaiting 2nd REGISTER with authorization header f_awaitingREGISTER(mw_REGISTER_unauthorizedRequest_IMS); // 200OK to complete the request v_passociated_url := vc_caller_From.addressField.nameAddr.addrSpec; f_sendResponse(m_Response_2xxonREGISTER_IMS(c_statusLine200, vc_callId, vc_cSeq, vc_callee_From, vc_callee_To, vc_via, vc_contact, p_to_user, v_passociated_url)); f_terminate_component(); } /** * @desc Terminates component with de-registration * @param p_to_user The selected user's SIP URL * @param p_qop of the peer UE (alternatively) */ function f_IMS_postamble_awaitDeRegistration( in SipUrl p_to_user, in charstring p_qop ) runs on ImsComponent { var SipUrl v_passociated_url; // Awaiting 1st REGISTER f_awaitingREGISTER(mw_REGISTER_unauthorizedRequest_IMS); // 401 response f_sendResponse(m_Response_WWWauthenticate_IMS(c_statusLine401, vc_callId, vc_cSeq, vc_caller_From, vc_caller_To, vc_via, m_wwwAuthenticate(f_calculatecChallenge_forWWWAuthorization(p_qop, valueof(vc_authorization.body[0].digestResponse))))); // Awaiting 2nd REGISTER with authorization header f_awaitingREGISTER(mw_REGISTER_unauthorizedRequest_IMS); // 200OK to complete the request v_passociated_url := vc_caller_From.addressField.nameAddr.addrSpec; f_sendResponse(m_Response_2xxonREGISTER_IMS(c_statusLine200, vc_callId, vc_cSeq, vc_callee_From, vc_callee_To, vc_via, vc_contact, p_to_user, v_passociated_url)); f_terminate_component(); } /** * @desc Awaits de-registration * @param p_to_user The selected user's SIP URL * @param p_qop of the peer UE (alternatively) */ function f_IMS_awaitDeRegistration( in SipUrl p_to_user, in charstring p_qop ) runs on ImsComponent { var SipUrl v_passociated_url; // Awaiting 1st REGISTER f_awaitingREGISTER(mw_REGISTER_unauthorizedRequest_IMS); // 401 response f_sendResponse(m_Response_WWWauthenticate_IMS(c_statusLine401, vc_callId, vc_cSeq, vc_caller_From, vc_caller_To, vc_via, m_wwwAuthenticate(f_calculatecChallenge_forWWWAuthorization(p_qop, valueof(vc_authorization.body[0].digestResponse))))); // Awaiting 2nd REGISTER with authorization header f_awaitingREGISTER(mw_REGISTER_unauthorizedRequest_IMS); // 200OK to complete the request v_passociated_url := vc_caller_From.addressField.nameAddr.addrSpec; f_sendResponse(m_Response_2xxonREGISTER_IMS(c_statusLine200, vc_callId, vc_cSeq, vc_callee_From, vc_callee_To, vc_via, vc_contact, p_to_user, v_passociated_url)); } //NOTE STF471: renamed f_SIP_postamble_UE(1|2)_withoutRegistration to f_SIP_postamble_UE_withoutRegistration /** * @desc Terminates component without registration */ function f_SIP_postamble_UE_withoutRegistration( ) runs on ImsComponent { f_terminate_component(); } /** * @desc Sends BYE and awaits response (IMS) * @param p_requestUri The Request URI * @param p_callId CallId parameter for outgoing BYE * @param p_cSeq_s CSeq parameter for outgoing BYE * @param p_from From parameter for outgoing BYE * @param p_to To parameter for outgoing BYE */ function f_terminateCall_IMS( SipUrl p_requestUri, CallId p_callId, inout CSeq p_cSeq_s, From p_from, template(value) To p_to ) runs on ImsComponent { LibSip_Steps.f_setHeadersBYE(p_cSeq_s); // Sending of a BYE request to release the call and expect a final response f_SendBYE(m_BYE_Request_IMS(p_requestUri, p_callId, p_cSeq_s, p_from, p_to, vc_via, vc_route)); tc_resp.start; alt { [] SIPP.receive(mw_Response_Base(mw_statusLine1xx, p_callId, p_cSeq_s)) { repeat; } [] SIPP.receive(mw_Response_Base(mw_statusLineFinal, p_callId, p_cSeq_s)) { tc_resp.stop; } // timeout should be handled in default_alt_step } } // end function f_terminateCall_IMS /** * @desc Sends BYE and awaits response (UE) * @param p_requestUri The Request URI * @param p_callId CallId parameter for outgoing BYE * @param p_cSeq_s CSeq parameter for outgoing BYE * @param p_from From parameter for outgoing BYE * @param p_to To parameter for outgoing BYE * @param p_recordRoute RecordRoute parameter for outgoing BYE - default: omit */ function f_terminateCall_UE( SipUrl p_requestUri, CallId p_callId, inout CSeq p_cSeq_s, From p_from, template(value) To p_to, template RecordRoute p_recordRoute := omit ) runs on ImsComponent { var Route v_route; LibSip_Steps.f_setHeadersBYE(p_cSeq_s); // Sending of a BYE request to release the call and expect a final response if (ispresent(p_recordRoute)) { v_route := {ROUTE_E, valueof(p_recordRoute.routeBody)}; f_SendBYE(m_BYE_Request_UE(p_requestUri, p_callId, p_cSeq_s, p_from, valueof(p_to), vc_via, v_route)); } else { f_SendBYE(m_BYE_Request_UE(p_requestUri, p_callId, p_cSeq_s, p_from, valueof(p_to), vc_via, vc_route)); } tc_resp.start; alt { [] SIPP.receive(mw_Response_Base(mw_statusLine1xx, p_callId, p_cSeq_s)) { repeat; } [] SIPP.receive(mw_Response_Base(mw_statusLineFinal, p_callId, p_cSeq_s)) { tc_resp.stop; } // timeout should be handled in default_alt_step } } // end function f_terminateCall_UE /** * @desc Sends BYE and awaits response and De-registration * @param p_requestUri The Request URI * @param p_callId CallId parameter for outgoing BYE * @param p_cSeq_s CSeq parameter for outgoing BYE * @param p_from From parameter for outgoing BYE * @param p_to To parameter for outgoing BYE * @param p_qop of the peer UE (alternatively) */ function f_terminateCall_UE_withDeReg( SipUrl p_requestUri, CallId p_callId, inout CSeq p_cSeq_s, From p_from, template(value) To p_to, in charstring p_qop ) runs on ImsComponent { LibSip_Steps.f_setHeadersBYE(p_cSeq_s); // Sending of a BYE request to release the call and expect a final response f_SendBYE(m_BYE_Request_UE(p_requestUri, p_callId, p_cSeq_s, p_from, p_to, vc_via, vc_route)); tc_resp.start; alt { [] SIPP.receive(mw_Response_Base(mw_statusLine1xx, p_callId, p_cSeq_s)) { repeat; } [] SIPP.receive(mw_Response_Base(mw_statusLineFinal, p_callId, p_cSeq_s)) { tc_resp.stop; } // timeout should be handled in default_alt_step } action("Please de-register"); f_IMS_awaitDeRegistration(p_requestUri, p_qop); } // end function f_terminateCall_UE_withDeReg } group defaults { /** * @desc Altstep for clearing registration (IMS user) * @param p_to_user The selected user's SIP URL * @param p_qop of the peer UE (alternatively) * @verdict fail for all unexpected branches */ altstep a_clearRegistration_IMSuser( in SipUrl p_to_user, in charstring p_qop ) runs on ImsComponent { var Response v_response; var Request v_request; var SUBSCRIBE_Request v_subscribe_request; var REGISTER_Request v_register_request; var BYE_Request v_bye_request; var CANCEL_Request v_cancel_request; var NOTIFY_Request v_notify_request; var INFO_Request v_info_request; var CSeq v_cSeq; [] any timer.timeout { log("*** " & testcasename() & ": FAIL: Timeout while waiting for message. ***"); setverdict(fail); all timer.stop; vc_callId := vc_callIdReg; action("Please de-register"); f_IMS_awaitDeRegistration(p_to_user, p_qop); f_componentStop(); } // allow repeated INVITEs [vc_ignore_invite] SIPP.receive(mw_INVITE_Request_Base) { repeat; } // allow repeated BYEs after ack of the first BYE [vc_ignore_bye] SIPP.receive(mw_BYE_Request_Base(?)) { repeat; } [] SIPP.receive(mw_ACK_Request_Base(?)) { repeat; } // allow 100 replies [] SIPP.receive(mw_Response_Base(c_statusLine100, ?, ?)) { repeat; } // ignore 181 if flag is set (following TS 183004 §4.5.2.1) [vc_ignore181] SIPP.receive(mw_Response_Base(c_statusLine181, vc_callId, vc_cSeq)) -> value v_response sender vc_sent_label { v_cSeq := valueof(v_response.msgHeader.cSeq); f_setHeadersOnReceiptOfResponse(v_response); repeat; } // according to SIP chap.8.1.3.2 [] SIPP.receive(mw_Response_Base(c_statusLine183, vc_callId, vc_cSeq)) { repeat; } // ignore 484 if flag is set [vc_ignore484] SIPP.receive(mw_Response_Base(c_statusLine484, vc_callId, vc_cSeq)) { repeat; } [vc_ignore4xx] SIPP.receive(mw_Response_Base(mw_statusLine4xx, vc_callId, ?)) -> value v_response sender vc_sent_label { v_cSeq := valueof(v_response.msgHeader.cSeq); f_setHeadersOnReceiptOfResponse(v_response); f_SendACK(m_ACK_Request_route(vc_requestUri, vc_callId, v_response.msgHeader.cSeq, vc_from, vc_to, vc_via, vc_route)); repeat; } [vc_ignore200OKinv] SIPP.receive(mw_Response_Base(c_statusLine200, vc_callId, ?)) { repeat; } [] SIPP.receive(mw_INFO_Request_Base(vc_callId)) -> value v_info_request sender vc_sent_label { f_setHeadersOnReceiptOfRequest(v_info_request); f_send200OK(); repeat; } // awaiting of Notify [] SIPP.receive(mw_NOTIFY_Request_Base(vc_callId)) -> value v_notify_request sender vc_sent_label { f_setHeadersOnReceiptOfRequest(v_notify_request); f_send200OK(); repeat; } // awaiting of subscribe from UE [vc_ignore_subscribe] SIPP.receive(mw_SUBSCRIBE_Request_Base) -> value v_subscribe_request sender vc_sent_label { f_setHeadersOnReceiptOfSUBSCRIBE(v_subscribe_request); f_send200OK(); repeat; } // awaiting of subscribe on proxy [] SIPP.receive(mw_SUBSCRIBE_Request_Base) -> value v_subscribe_request sender vc_sent_label { f_setHeadersOnReceiptOfRequest(v_subscribe_request); f_sendResponse(m_Response_Contact(c_statusLine200, vc_callId, vc_cSeq, vc_callee_From, vc_callee_To, vc_via, vc_contact)); f_SendNOTIFY(m_NOTIFY_Request_contact(v_subscribe_request.msgHeader.contact.contactBody.contactAddresses[0].addressField.nameAddr.addrSpec, vc_callId, vc_cSeq, vc_callee_From, vc_callee_To, vc_via, vc_contact)); f_awaitingOkResponse(vc_cSeq); repeat; } // unexpected BYE is acknowledged to avoid retransmissions [] SIPP.receive(mw_BYE_Request_Base(?)) -> value v_bye_request sender vc_sent_label { log("*** " & testcasename() & ": FAIL: Unexpected BYE message received. ***"); setverdict(fail); f_setHeadersOnReceiptOfRequest(v_bye_request); f_send200OK(); action("Please de-register"); f_IMS_awaitDeRegistration(p_to_user, p_qop); f_componentStop(); } // unexpected CANCEL is acknowledged to avoid retransmissions [] SIPP.receive(mw_CANCEL_Request_Base(?)) -> value v_cancel_request sender vc_sent_label { log("*** " & testcasename() & ": FAIL: Unexpected CANCEL message received. ***"); setverdict(fail); f_setHeadersOnReceiptOfRequest(v_cancel_request); // Answer to the CANCEL f_send200OK(); action("Please de-register"); f_IMS_awaitDeRegistration(p_to_user, p_qop); f_componentStop(); } // catch 4xx response [] SIPP.receive(mw_Response_Base(mw_statusLine4xx, vc_callId, ?)) -> value v_response sender vc_sent_label { log("*** " & testcasename() & ": FAIL: Unexpected 4xx response received. ***"); setverdict(fail); v_cSeq := valueof(v_response.msgHeader.cSeq); f_setHeadersOnReceiptOfResponse(v_response); LibSip_Steps.f_setHeadersACK(); f_SendACK(m_ACK_Request_route(vc_requestUri, vc_callId, v_response.msgHeader.cSeq, vc_from, vc_to, vc_via, vc_route)); action("Please de-register"); f_IMS_awaitDeRegistration(p_to_user, p_qop); f_componentStop(); } // catch 5xx response [] SIPP.receive(mw_Response_Base(mw_statusLine5xx, vc_callId, ?)) -> value v_response sender vc_sent_label { log("*** " & testcasename() & ": FAIL: Unexpected 5xx response received. ***"); setverdict(fail); v_cSeq := valueof(v_response.msgHeader.cSeq); f_setHeadersOnReceiptOfResponse(v_response); LibSip_Steps.f_setHeadersACK(); f_SendACK(m_ACK_Request_route(vc_requestUri, vc_callId, v_response.msgHeader.cSeq, vc_from, vc_to, vc_via, vc_route)); action("Please de-register"); f_IMS_awaitDeRegistration(p_to_user, p_qop); f_componentStop(); } // catch invalid REGISTER [] SIPP.receive(mw_REGISTER_Request_Base) -> value v_register_request sender vc_sent_label { log("*** " & testcasename() & ": FAIL: Unexpected REGISTER received. ***"); setverdict(fail); f_componentStop(); } // any [] SIPP.receive { log("*** " & testcasename() & ": FAIL: Unexpected message received. ***"); setverdict(fail); all timer.stop; action("Please de-register"); f_IMS_awaitDeRegistration(p_to_user, p_qop); f_componentStop(); } } /** * @desc Main default altstep to handle unexpected messages and timeout * @verdict fail for all unexpected branches */ altstep a_altstep_AS( ) runs on SipComponent { var Request v_request; var REGISTER_Request v_register_request; var BYE_Request v_bye_request; var CANCEL_Request v_cancel_request; [] any timer.timeout { log("*** " & testcasename() & ": FAIL: Timeout while waiting for message. ***"); setverdict(fail); all timer.stop; } // allow repeated INVITEs [vc_ignore_invite] SIPP.receive(mw_INVITE_Request_Base) { repeat; } // handle REGISTER requests [] SIPP.receive(mw_REGISTER_Request_Base) -> value v_register_request sender vc_sent_label { f_setHeadersOnReceiptOfREGISTER(v_register_request); // vc_contact := vc_request.msgHeader.contact; f_sendResponse(m_Response_Contact(c_statusLine200, vc_callId, vc_cSeq, vc_caller_From, vc_caller_To, vc_via, vc_contact)); repeat; } // according to SIP chap.8.1.3.2 [] SIPP.receive(mw_Response_Base(c_statusLine183, vc_callId, vc_cSeq)) { repeat; } // unexpected CANCEL is acknowledged to avoid retransmissions [] SIPP.receive(mw_CANCEL_Request_Base(?)) -> value v_cancel_request sender vc_sent_label { log("*** " & testcasename() & ": FAIL: Unexpected CANCEL message received. ***"); setverdict(fail); f_setHeadersOnReceiptOfRequest(v_cancel_request); f_send200OK(); } // unexpected BYE is acknowledged to avoid retransmissions [] SIPP.receive(mw_BYE_Request_Base(?)) -> value v_bye_request sender vc_sent_label { log("*** " & testcasename() & ": FAIL: Unexpected BYE message received. ***"); setverdict(fail); f_setHeadersOnReceiptOfRequest(v_bye_request); f_send200OK(); } [] SIPP.receive(mw_Response_Base(?, vc_callId, vc_cSeq)) -> value vc_response { log("*** " & testcasename() & ": FAIL: Unexpected response message in " & __SCOPE__ & " received. ***"); setverdict(fail); repeat; } // any [] SIPP.receive { log("*** " & testcasename() & ": FAIL: Unexpected message received. ***"); setverdict(fail); all timer.stop; } } } } // module LibIms_Steps