source: trunk/ETSI-Testsuites/ETSI_auto_IOT/codec/validation/LibSip_Steps.ttcn @ 26

Last change on this file since 26 was 22, checked in by rings, 14 years ago
  • Property svn:executable set to *
File size: 111.7 KB
Line 
1/*
2 *      @author         STF 346, STF366, STF368, STF369
3 *  @version    $Id: LibSip_Steps.ttcn 350 2009-05-22 08:18:45Z saiu $
4 *      @desc           This module provides the types used by the test component
5 *              for SIP-IMS tests.
6 */
7
8module LibSip_Steps language "TTCN-3:2005"//MRO
9{       
10        //LibCommon
11        import from LibCommon_Sync all ;
12        import from LibCommon_VerdictControl all ;
13        //LibSip
14        import from LibSip_SIPTypesAndValues all;
15        import from LibSip_SDPTypes all;
16        import from LibSip_Templates all;
17        import from LibSip_Interface all;
18        import from LibSip_PIXITS all;
19        import from LibSip_XMLTypes all;
20
21group externalfunctions {
22       
23        //Return random charstring
24        external function fx_rndStr() return charstring;
25        // Return the equivalent string in lower case
26        external function fx_putInLowercase(charstring par_string) return charstring;
27       
28        external function fx_getIpAddr(charstring host_name) return charstring;
29
30        // External function to generate a digest response.
31        // References:
32        //   * RFC 2617 HTTP Authentication: Basic and Digest Access
33        //     Authentication, and
34        //   * RFC 1321 The MD5 Message-Digest Algorithm
35        // See RFC 2617, chapter 5 Sample implementation, for example usage, as
36        // the signature of calculateDigestResponse is according to the example
37        // given in the RFC.
38        //
39        external function fx_calculateDigestResponse(
40          charstring nonce,
41          charstring cnonce,
42          charstring user,
43          charstring realm,
44          charstring passwd,
45          charstring alg,
46          charstring nonceCount,
47          charstring method,
48          charstring qop,
49          charstring URI,
50          charstring HEntity) return charstring;
51
52}
53
54group ParameterOperations {
55
56        /**
57         *
58         * @desc function to generate a 32 bits random number as a charstring for tag field
59         * (used as e.g.: tag in from-header field, or branch parameter in via header)
60         * @return random value with at least 32 bits of randomness
61         *
62         */
63         function f_getRndTag() return charstring
64        {
65          var charstring tag_value;
66          //tag_value is initialized with a random value with at least 32 bits of randomness
67          // 4294967296 is a 32 bits integer
68          tag_value := fx_rndStr()&fx_rndStr();
69          return(tag_value);
70        }
71
72        /**
73         *
74         * @desc  Function to prepare credentials for request that has an empty
75         * entity body such as a REGISTER message.
76         * @param p_userprofile to get important parameters
77         * @return Credentials field
78         */
79        function f_calculatecCredentials_empty(in SipUserProfile p_userprofile) return Credentials
80        {
81          var Credentials v_result;
82             
83          var charstring v_nonce := "";
84             
85          // RFC 2617 3.2.2 username:
86          // The name of user in the specified realm.
87          var charstring v_username := p_userprofile.privUsername;
88             
89          var charstring v_realm := p_userprofile.registrarDomain;
90             
91          var charstring v_uri := c_sipScheme & ":" & p_userprofile.registrarDomain;
92                   
93          var charstring v_response := "";
94         
95          // Construct credentials for an Authorization field of a request.
96          v_result :=
97          {
98                digestResponse :=
99                {
100                  { id := "Digest username", paramValue := v_username },
101                  { id := "realm", paramValue := v_realm },
102                  { id := "uri", paramValue := v_uri },
103                  { id := "nonce=""""", paramValue := omit }, // already enclosed to " characters
104                  { id := "response=""""", paramValue := omit } // already enclosed to " characters
105                }
106          };
107             
108          return v_result;
109        }
110
111
112        /**
113         *
114         * @desc  Function to calculate credentials for request that has an empty
115         * entity body such as a REGISTER message.
116         * @param p_userprofile to get important parameters
117         * @param p_method (can be "REGISTER", "INVITE",....)
118         * @param p_challenge parameter from 4xx response
119         * @return Credentials field
120         * @verdict
121         */
122        function f_calculatecCredentials(in SipUserProfile p_userprofile, in charstring p_method,
123                in CommaParam_List p_challenge) return Credentials
124        {
125          var Credentials v_result;
126     
127          var charstring v_nonce := "";
128     
129          // Use a fixed client nonce.
130          var charstring v_cnonce := "1317265";
131     
132          // RFC 2617 3.2.2 username:
133          // The name of user in the specified realm.
134          var charstring v_username := p_userprofile.privUsername;
135     
136          var charstring v_realm;
137     
138          // RFC 2617 3.2.2.2 passwd:
139          // A known shared secret, the password of user of the specified
140          // username.
141          var charstring v_passwd := p_userprofile.passwd;
142     
143          var charstring v_algorithm;
144     
145          // Use a fixed nonce count.
146          const charstring c_nonceCount := "00000002";
147
148          var charstring v_qop := p_userprofile.qop;
149     
150          var charstring v_uri := c_sipScheme & ":" & p_userprofile.registrarDomain;
151     
152          // MD5 hash of empty entity body.
153          const charstring c_hEntity := "d41d8cd98f00b204e9800998ecf8427e";
154     
155          var charstring v_response;
156          var charstring v_opaque;
157     
158     
159          // extract nonce, realm, algorithm, and opaque from challenge
160     
161          v_nonce := f_extractParamValueFromChallenge(p_challenge, "nonce");
162          v_realm := f_extractParamValueFromChallenge(p_challenge, "realm");
163          v_algorithm := f_extractParamValueFromChallenge(p_challenge, "algorithm");
164          v_opaque := f_extractParamValueFromChallenge(p_challenge, "opaque");
165     
166          // calculate a digest response for the Authorize header
167          v_response := fx_calculateDigestResponse(
168                v_nonce,
169                v_cnonce,
170                v_username,
171                v_realm,
172                v_passwd,
173                v_algorithm,
174                c_nonceCount,
175                p_method,
176                v_qop,
177                v_uri,
178                c_hEntity);
179     
180          // Construct credentials for an Authorization field of a request.
181          v_result :=
182          {
183                digestResponse :=
184                {
185                  { id := "Digest username", paramValue := v_username },
186                  { id := "realm", paramValue := v_realm },
187                  { id := "nonce", paramValue := v_nonce },
188                  { id := "uri", paramValue := v_uri },
189                  { id := "response", paramValue := v_response },
190                  { id := "algorithm=md5", paramValue := omit }, // algorithm is not enclosed to " characters
191                  { id := "cnonce", paramValue := v_cnonce },
192                  { id := "opaque=""""", paramValue := omit }, // already enclosed to " characters
193                  { id := "qop="&v_qop, paramValue := omit },//qop
194                  { id := "nc="&c_nonceCount, paramValue := omit }//nonceCount
195                }
196          };
197     
198          return v_result;
199        }
200
201        /**
202         *
203         * @desc  Function to calculate credentials for request that has an empty
204         * entity body such as a REGISTER message. NO RESPONSE value to cause an error!
205         * @param p_userprofile to get important parameters
206         * @param p_method (can be "REGISTER", "INVITE",....)
207         * @param p_challenge parameter from 4xx response
208         * @return Credentials field
209         * @verdict
210         */
211        function f_calculatecCredentials_wo_response(in SipUserProfile p_userprofile, in charstring p_method,
212                in CommaParam_List p_challenge) return Credentials
213        {
214          var Credentials v_result;
215     
216          var charstring v_nonce := "";
217     
218          // Use a fixed client nonce.
219          var charstring v_cnonce := "1317265";
220     
221          // RFC 2617 3.2.2 username:
222          // The name of user in the specified realm.
223          var charstring v_username := p_userprofile.privUsername;
224     
225          var charstring v_realm;
226     
227          // RFC 2617 3.2.2.2 passwd:
228          // A known shared secret, the password of user of the specified
229          // username.
230          var charstring v_passwd := p_userprofile.passwd;
231     
232          var charstring v_algorithm;
233     
234          // Use a fixed nonce count.
235          const charstring c_nonceCount := "00000002";
236
237          var charstring v_qop := p_userprofile.qop;
238     
239          var charstring v_uri := c_sipScheme & ":" & p_userprofile.registrarDomain;
240     
241          // MD5 hash of empty entity body.
242          const charstring c_hEntity := "d41d8cd98f00b204e9800998ecf8427e";
243     
244          var charstring v_response;
245          var charstring v_opaque;
246     
247     
248          // extract nonce, realm, algorithm, and opaque from challenge
249     
250          v_nonce := f_extractParamValueFromChallenge(p_challenge, "nonce");
251          v_realm := f_extractParamValueFromChallenge(p_challenge, "realm");
252          v_algorithm := f_extractParamValueFromChallenge(p_challenge, "algorithm");
253          v_opaque := f_extractParamValueFromChallenge(p_challenge, "opaque");
254     
255          // calculate a digest response for the Authorize header
256          v_response := fx_calculateDigestResponse(
257                v_nonce,
258                v_cnonce,
259                v_username,
260                v_realm,
261                v_passwd,
262                v_algorithm,
263                c_nonceCount,
264                p_method,
265                v_qop,
266                v_uri,
267                c_hEntity);
268     
269          // Construct credentials for an Authorization field of a request.
270          v_result :=
271          {
272                digestResponse :=
273                {
274                  { id := "Digest username", paramValue := v_username },
275                  { id := "realm", paramValue := v_realm },
276                  { id := "nonce", paramValue := v_nonce },
277                  { id := "uri", paramValue := v_uri },
278//                { id := "response", paramValue := v_response }, // not included to cause an error
279                  { id := "algorithm=md5", paramValue := omit }, // algorithm is not enclosed to " characters
280                  { id := "cnonce", paramValue := v_cnonce },
281                  { id := "opaque=""""", paramValue := omit }, // already enclosed to " characters
282                  { id := "qop="&v_qop, paramValue := omit },//qop
283                  { id := "nc="&c_nonceCount, paramValue := omit }//nonceCount
284                }
285          };
286     
287          return v_result;
288        }
289
290        /**
291         *
292         * @desc  Function to calculate credentials for response 401 - WWW-Authorization
293         * @param p_qop of the peer UE (alternatively )
294         * @param p_challenge parameter from 1st REGISTER request
295         * @return Credentials field
296         * @verdict
297         */
298        function f_calculatecChallenge_forWWWAuthorization(in charstring p_qop, in CommaParam_List p_challenge) return Challenge
299        {
300          var Challenge v_result;
301
302          var charstring v_realm;
303     
304          var charstring v_qop := p_qop;
305
306          v_realm := f_extractParamValueFromChallenge(p_challenge, "realm");
307     
308          // Construct credentials for an Authorization field of a request.
309          v_result :=
310          {
311                digestCln :=
312                {
313                  { id := "Digest realm", paramValue := v_realm },
314                  { id := "nonce=", paramValue := c_nonce },
315                  { id := "algorithm=", paramValue := c_algorithm }, // algorithm is not enclosed to " characters
316                  { id := "ck=", paramValue := c_ck },
317                  { id := "ik=", paramValue := c_ik }, // already enclosed to " characters
318                  { id := "qop="&v_qop, paramValue := omit }//qop
319
320                }
321          };
322     
323          return v_result;
324        }
325       
326        /**
327        *
328        * @desc  Function to calculate credentials for request that has an empty
329        * entity body such as a REGISTER message and at the end put different private name
330        * @param p_userprofile to get important parameters
331        * @param p_method (can be "REGISTER", "INVITE",....)
332        * @param p_challenge parameter from 4xx response
333        * @return Credentials field
334        * @verdict
335        */
336   function f_calculatecCredentialsAndChangeUserName(in SipUserProfile p_userprofile, in charstring p_method,
337           in CommaParam_List p_challenge) return Credentials
338   {
339         var Credentials v_result;
340     
341         var charstring v_nonce := "";
342     
343         // Use a fixed client nonce.
344         var charstring v_cnonce := "1317265";
345     
346         // RFC 2617 3.2.2 username:
347         // The name of user in the specified realm.
348         var charstring v_username := p_userprofile.privUsername;
349     
350         var charstring v_realm;
351     
352         // RFC 2617 3.2.2.2 passwd:
353         // A known shared secret, the password of user of the specified
354         // username.
355         var charstring v_passwd := p_userprofile.passwd;
356     
357         var charstring v_algorithm;
358     
359         // Use a fixed nonce count.
360         const charstring c_nonceCount := "00000002";
361
362         var charstring v_qop := p_userprofile.qop;
363     
364         var charstring v_uri := c_sipScheme & ":" & p_userprofile.registrarDomain;
365     
366         // MD5 hash of empty entity body.
367         const charstring c_hEntity := "d41d8cd98f00b204e9800998ecf8427e";
368     
369         var charstring v_response;
370         var charstring v_opaque;
371     
372     
373         // extract nonce, realm, algorithm, and opaque from challenge
374     
375         v_nonce := f_extractParamValueFromChallenge(p_challenge, "nonce");
376         v_realm := f_extractParamValueFromChallenge(p_challenge, "realm");
377         v_algorithm := f_extractParamValueFromChallenge(p_challenge, "algorithm");
378         v_opaque := f_extractParamValueFromChallenge(p_challenge, "opaque");
379     
380         // calculate a digest response for the Authorize header
381         v_response := fx_calculateDigestResponse(
382           v_nonce,
383           v_cnonce,
384           v_username,
385           v_realm,
386           v_passwd,
387           v_algorithm,
388           c_nonceCount,
389           p_method,
390           v_qop,
391           v_uri,
392           c_hEntity);
393     
394         // Construct credentials for an Authorization field of a request.
395         v_result :=
396         {
397           digestResponse :=
398           {
399                 { id := "Digest username", paramValue := "DifferentToPrivateUser"},
400                 { id := "realm", paramValue := v_realm },
401                 { id := "nonce", paramValue := v_nonce },
402                 { id := "uri", paramValue := v_uri },
403                 { id := "response", paramValue := v_response },
404                 { id := "algorithm=md5", paramValue := omit }, // algorithm is not enclosed to " characters
405                 { id := "cnonce", paramValue := v_cnonce },
406                 { id := "opaque=""""", paramValue := omit }, // already enclosed to " characters
407                 { id := "qop="&v_qop, paramValue := omit },//qop
408                 { id := "nc="&c_nonceCount, paramValue := omit }//nonceCount
409           }
410         };
411     
412         return v_result;
413   }
414       
415
416   /**
417        *
418        * @desc Function to check if param related to id from CommanParam_List exist
419        * containing challenge.
420        * @param p_challenge parameter from 4xx response
421        * @param p_id name of parameter("nonce", "realm", "ck", "ik"...)
422        * @return  parameter p_id value
423        */
424   function f_checkParamValueFromChallengeIfPresent(in CommaParam_List p_challenge, in charstring p_id) return boolean
425   {
426         var boolean v_result := false;
427         var integer v_len := sizeof(p_challenge);
428         var charstring v_id := fx_putInLowercase(p_id);
429     
430         for (var integer i := 0; i < v_len; i := i + 1)
431         {
432           if (fx_putInLowercase(p_challenge[i].id) == v_id)
433           {
434                 v_result := true;
435           }
436         }
437     
438         return v_result;
439   }   
440   
441    /**
442        *
443        * @desc Function to check if tag is present in SemicolonParam_List
444        * @param p_param_l SemicolonParam_List
445        * @return  boolean  true if tag is present
446        */
447    function f_checkTagPresent(SemicolonParam_List p_param_l) runs on SipComponent return boolean {
448            var integer v_numberOfParams;
449            var integer i := 0;
450
451            v_numberOfParams := sizeof (p_param_l);
452            while (i < v_numberOfParams) {
453                    if (fx_putInLowercase(p_param_l[i].id) == c_tagId) {
454                            return (true);
455                    }
456                    i := i + 1;
457            }
458            return (false);
459    }
460
461        /**
462         *
463         * @desc Function to extract paramValue related to id from CommanParam_List
464         * containing challenge.
465         * @param p_challenge parameter from 4xx response
466         * @param p_id name of parameter("nonce", "realm",...)
467         * @return  parameter p_id value
468         */
469        function f_extractParamValueFromChallenge(in CommaParam_List p_challenge, in charstring p_id) return charstring
470        {
471          var charstring v_result := "";
472          var integer v_len := sizeof(p_challenge);
473          var charstring v_id := fx_putInLowercase(p_id);
474     
475          for (var integer i := 0; i < v_len; i := i + 1)
476          {
477                if (fx_putInLowercase(p_challenge[i].id) == v_id)
478                {
479                  v_result := p_challenge[i].paramValue;
480                }
481          }
482
483          if (v_result == "")
484          {
485                if(match(p_id,"algorithm"))
486                {
487                        v_result := "MD5"
488                }
489                else if(match(p_id,"opaque"))
490                {
491                        v_result := ""
492                }
493                else
494                {
495                var charstring v_tmpchar := "Cannot acquire value from credentials.";
496                log ("Cannot acquire value from credentials.");
497                setverdict(inconc);
498                stop;
499                }
500          }
501     
502          return v_result;
503        }
504       
505}//end group ParameterOperations
506
507group FieldOperations {
508
509        /**
510         *
511         * @desc function adds "Tag"-parameter in "To"-headerfield
512         * @param p_to To header field that should get a Tag parameter
513         *
514         */
515        function f_addTagInTo(inout To p_to) runs on SipComponent
516        {     
517          f_addParameterTagIfNotPresent(c_tagId, f_getRndTag(), p_to);
518        }
519
520        /**
521         *
522         * @desc addition of a single parameter in the via header field
523         * @param p_parameter_name name of parameter to be added
524         * @param p_parameter_value value of parameter to be added
525         * @param p_viaBody the via parameter to be extended
526         * @verdict
527         */
528        function f_addParameterIfNotPresent(
529                in charstring p_parameter_name,
530                in charstring p_parameter_value,
531                inout ViaBody p_viaBody)
532               
533                {
534                if (ispresent (p_viaBody.viaParams)) {
535                        return;
536                }
537                p_viaBody.viaParams := {
538                        {
539                                p_parameter_name,
540                                p_parameter_value
541                        }
542                };
543        }   
544   
545        /**
546         *
547         * @desc function to addd a parameter to the "To" header field (if there is not any parameter)
548         * @param p_parameter_name name of the parameter to be added
549         * @param p_parameter_value value of the paramter to be added
550         * @param p_to "To" header field to be extended
551         * @verdict
552         */
553        function f_addParameterTagIfNotPresent(
554                in charstring p_parameter_name,
555                in charstring p_parameter_value,
556                inout To p_to)
557               
558                {
559                if (ispresent (p_to.toParams)) {
560                        return;
561                }
562                p_to.toParams := {
563                        {
564                                p_parameter_name,
565                                p_parameter_value
566                        }
567                };
568        }
569
570        /**
571         *
572         * @desc function compares the IP address of two hosts
573         * @param p_host1 hostname
574         * @param p_host2 hostname
575         * @return boolean value that is true if the IP addresses are identical
576         * @verdict
577         */     
578        function f_equivalentHostAddr(in charstring p_host1,  in charstring p_host2) return boolean
579        {
580          //A DNS server may be used
581          return(fx_getIpAddr(p_host1) == fx_getIpAddr(p_host2));
582        }
583
584
585        /**
586                *
587                * @desc function checks if Require contains Precondition
588                * @param p_message (request or response) SIP message to be analysed
589                * @return true if p_id parameter exist
590                */
591        function f_checkRequirePrecondition(in Request p_message)
592        {
593                if (ispresent(p_message.msgHeader.require))
594                {
595                        var boolean v_precondition_found:=false;
596                        for (var integer v_i:=0; v_i<sizeof(p_message.msgHeader.require.optionsTags); v_i:=v_i+1){                     
597                                if (match(p_message.msgHeader.require.optionsTags[v_i],c_tagPrecond)) {
598                                        v_precondition_found:=true;
599                                }
600                        }
601                        if (not(v_precondition_found)){
602                                setverdict(fail);
603                                log("FAIL: precondition not found in Require options list!");
604                        }
605                }
606                else
607                {
608                        setverdict(fail);
609                        log("FAIL: Require options is not present!");
610                }
611        }
612
613        /**
614         *
615         * @desc function checks if P-Charging-Vector contains a particular parameter
616         * @param p_message (request or response) SIP message to be analysed
617         * @param p_id name of parameter
618         * @return true if p_id parameter exist
619         */
620        function f_checkPChargingVectorHeaderParamId(in Request p_message, charstring p_id) return boolean
621        {
622          var integer v_chargeParamsLen;
623         
624          if (ispresent(p_message.msgHeader.pChargingVector)) {         
625                for (var integer i:=0; i<sizeof(p_message.msgHeader.pChargingVector.chargeParams); i:=i+1)
626                                {if(p_message.msgHeader.pChargingVector.chargeParams[i].id == p_id)
627                                        {return (true)}
628                                };
629          }
630          return (false)
631        }
632
633        /**
634         *
635         * @desc function checks if P-Charging-Vector contains a particular parameter
636         * @param p_message (request or response) SIP message to be analysed
637         * @param p_id name of parameter
638         * @return true if p_id parameter exist
639         */
640        function f_checkPChargingVectorHeaderParamIdResponse(in Response p_message, charstring p_id) return boolean
641        {
642          var integer v_chargeParamsLen;
643         
644          if (ispresent(p_message.msgHeader.pChargingVector)) {         
645                for (var integer i:=0; i<sizeof(p_message.msgHeader.pChargingVector.chargeParams); i:=i+1)
646                                {if(p_message.msgHeader.pChargingVector.chargeParams[i].id == p_id)
647                                        {return (true)}
648                                };
649          }
650          return (false)
651        }
652
653        /**
654         *
655         * @desc function returns the Host/Port of a given Contact header field
656         * @param p_contact contact header field to be analysed
657         * @return Host/Port record  from the contact header field
658         */
659        function f_getContactAddr(in ContactAddress p_contact) runs on SipComponent return HostPort
660          {
661                var HostPort v_locAddr;
662                var SipUrl    v_SipUrl;
663     
664                if (ischosen(p_contact.addressField.nameAddr))
665                {
666                  v_SipUrl := p_contact.addressField.nameAddr.addrSpec;
667                }
668                else
669                {
670                  v_SipUrl := p_contact.addressField.addrSpecUnion;
671                }
672     
673                v_locAddr.host := v_SipUrl.hostPort.host;
674     
675                if (ispresent(v_SipUrl.hostPort.portField))
676                {
677                        v_locAddr.portField := v_SipUrl.hostPort.portField;
678                }
679                else
680                {
681                        v_locAddr.portField := c_defaultSipPort;
682                }
683     
684                return(v_locAddr);
685          } // end f_getContactAddr
686
687        /**
688                *
689                * @desc function checks if History-Info-Header of the p_message contains a particular URI
690                * @param p_message (request or response) SIP message to be analysed
691                * @param p_URI name of parameter
692                * @return true if p_URI parameter exist
693                */
694        function f_checkHeaderInfoURI(in Response p_message, SipUrl p_URI) return boolean
695        {
696                        var integer v_chargeParamsLen;
697         
698                        if (ispresent(p_message.msgHeader.historyInfo)) {               
699                for (var integer i:=0; i<sizeof(p_message.msgHeader.historyInfo.historyInfoList); i:=i+1)
700                                {if(p_message.msgHeader.historyInfo.historyInfoList[i].nameAddr.addrSpec == p_URI)
701                                        {return (true)}
702                                };
703                        }
704                        return (false)
705        }
706       
707        /**
708        *
709        * @desc function returns the Userinfo from  a given To header field
710        * @param p_to To header field to be analysed
711        * @return Userinfo from the To header field as a charstring
712        */
713        function f_getUserfromTo(in To p_to) runs on SipComponent return charstring
714        {
715                var SipUrl    v_SipUrl;
716 
717                if (ischosen(p_to.addressField.nameAddr))
718                {
719                        v_SipUrl := p_to.addressField.nameAddr.addrSpec;
720                }
721                else
722                {
723                        v_SipUrl := p_to.addressField.addrSpecUnion;
724                }
725 
726                return(v_SipUrl.userInfo.userOrTelephoneSubscriber);
727        } // end f_getUserfromTo
728
729        /**
730         *
731         * @desc function to generate a 32 bits random number as a charstring for tag field
732         * @param p_cSeq_s CSeq parameter used to modify the tag field value
733         * @return tag value
734         */
735        function f_getRndCallId(inout CSeq p_cSeq_s) return charstring
736        {
737          var charstring v_tag_value;
738          v_tag_value := fx_rndStr()&fx_rndStr();
739          //v_tag_value is initialized with a random value with at least 32 bits of randomness
740          // 4294967296 is a 32 bits integer
741          //v_tag_value := int2str(float2int(4294967296.0*rnd()) + loc_CSeq_s.seqNumber );
742          return(v_tag_value);
743        }
744
745        /**
746         *
747         * @desc function give access to the top element of the Path header field.
748         * @param p_Request SIP message to be analysed
749         * @return NameAddr (e.g. <sip:p.home.com>) or omit
750         */
751        function f_getPathHeaderTop(inout Request p_Request) return template NameAddr
752        {
753          if (ispresent(p_Request.msgHeader.path)) {
754                if (sizeof(p_Request.msgHeader.path.pathValues)>0) {
755                        return(p_Request.msgHeader.path.pathValues[0].nameAddr)}
756                };
757          return(omit)
758        }
759
760        /**
761         *
762         * @desc function updates first element of a Via headerfield list
763         * @param p_viaBody_List address list of a Via header field
764         * @param p_source_address address to be inserted in the top element
765         */
766        function f_getViaReplyAddr(inout ViaBody_List p_viaBody_List, inout address4SIP p_source_address)
767         runs on SipComponent
768         {     
769           var ViaBody  v_viaBody;
770           var HostPort v_locAddr;
771           // The address to send message shall be updated after getting information
772           // in the Via header fied and according to 18.2.2
773           v_viaBody := p_viaBody_List[0];
774     
775           // received parameter has to be addded to the via hader field
776           // Be careful it could be an Host name and not an IP Address
777
778           if (not f_equivalentHostAddr(valueof (v_viaBody.sentBy.host),
779                   valueof (p_source_address.host))) {
780                   f_addParameterIfNotPresent(
781                           c_receivedId,
782                           valueof (p_source_address.host),
783                           v_viaBody);
784           }
785           if (ispresent(v_viaBody.sentBy.portField))
786           {
787                 p_source_address.portField := valueof(v_viaBody.sentBy.portField);
788           }
789           else
790           {
791                 p_source_address.portField := c_defaultSipPort;
792           }
793         }
794 
795        /**
796         *
797         * @desc functions give access to an element of the Route header field (record).
798         * @param p_message (request) SIP message to be analysed
799         * @param p_index index of Route record element to be retrieved
800         * @return HostPort value of the Route element or omit
801         */
802        function f_getRouteHeaderElementAddressFromRequest(in Request p_message, in integer p_index) return HostPort
803        {
804          if (ispresent(p_message.msgHeader.route)) {
805                if (sizeof(p_message.msgHeader.route.routeBody)>p_index) {
806                        return(p_message.msgHeader.route.routeBody[p_index].nameAddr.addrSpec.hostPort)}
807                };
808        setverdict(fail);
809        return(c_hostport_dummy)
810        }
811
812        /**
813         *
814         * @desc functions give access to an element of the Record-Route header field (record).
815         * @param p_message (request) SIP message to be analysed
816         * @param p_index index of recordRoute record element to be retrieved
817         * @return HostPort value of the Record-Route element or omit
818         */
819        function f_getRecordRouteHeaderElementAddressFromRequest(in Request p_message, in integer p_index) return HostPort
820        {
821          if (ispresent(p_message.msgHeader.recordRoute)) {
822                if (sizeof(p_message.msgHeader.recordRoute.routeBody)>p_index) {
823                        return(p_message.msgHeader.recordRoute.routeBody[p_index].nameAddr.addrSpec.hostPort)}
824                };
825        setverdict(fail);
826        return(c_hostport_dummy)
827        }
828   
829        /**
830         *
831         * @desc functions give access to an element of the Record-Route header field (record).
832         * @param p_message (response) SIP message to be analysed
833         * @param p_index index of recordRoute record element to be retrieved
834         * @return HostPort value of the Record-Route element or omit
835         */
836        function f_getRecordRouteHeaderElementAddressFromResponse(in Response p_message, in integer p_index) return HostPort
837        {
838          if (ispresent(p_message.msgHeader.recordRoute)) {
839                if (sizeof(p_message.msgHeader.recordRoute.routeBody)>p_index) {
840                        return(p_message.msgHeader.recordRoute.routeBody[p_index].nameAddr.addrSpec.hostPort)}
841                };
842        setverdict(fail);
843        return(c_hostport_dummy)
844        }
845   
846        /**
847         *
848         * @desc functions give access to an element of the Via header field (record).
849         * @param p_message (request) SIP message to be analysed
850         * @param p_index index of via record element to be retrieved
851         * @return HostPort value of the Via element or omit
852         */
853        function f_getViaHeaderElementHostPort(in Request p_message, in integer p_index) return HostPort
854        {
855       
856                if (sizeof(p_message.msgHeader.via.viaBody)>p_index) {
857                        return(p_message.msgHeader.via.viaBody[p_index].sentBy)}
858        setverdict(fail);
859        return(c_hostport_dummy)
860        }
861       
862        /**
863         *
864         * @desc functions give access to an element of the Via header field (record).
865         * @param p_message (response) SIP message to be analysed
866         * @param p_index index of via record element to be retrieved
867         * @return HostPort value of the Via element or omit
868         */     function f_getViaHeaderElementHostPortResponse(in Response p_message, in integer p_index) return HostPort
869        {
870       
871                if (sizeof(p_message.msgHeader.via.viaBody)>p_index) {
872                        return(p_message.msgHeader.via.viaBody[p_index].sentBy)}
873        setverdict(fail);
874        return(c_hostport_dummy)
875        }       
876       
877        /**
878         *
879         * @desc function checks indicators if topology hiding (TH) has been applied:
880         *      - second element in via-header record has tokenized-by parameter
881         * @param p_Request SIP message to be analysed
882         * @return boolean value (true indicate TH, false otherwise)
883         */
884        function f_topologyHiding(inout Request p_request) runs on SipComponent return boolean
885        {
886          var GenericParam v_viaParameter := p_request.msgHeader.via.viaBody[1].viaParams[0]; // second element
887          if (not v_viaParameter.id == "tokenized-by")
888                 {return(false)};
889          return(true)
890        }
891
892        /**
893         *
894         * @desc function checks indicators if topology hiding (TH) has been applied:
895         *      - any element in via-header record has tokenized-by parameter
896         * @param Response SIP message to be analysed
897         * @return boolean value (true indicate TH, false otherwise)
898         */
899        function f_topologyHidingResponse(inout Response p_response) runs on SipComponent return boolean
900        {
901         var GenericParam v_viaParameter;
902       
903         for (var integer v_i := 0; v_i < sizeof(p_response.msgHeader.via.viaBody); v_i := v_i + 1) {
904               
905          v_viaParameter := p_response.msgHeader.via.viaBody[v_i].viaParams[0]; // first parameter
906
907          if (not v_viaParameter.id == "tokenized-by")
908                 {return(false)}
909         }
910         return(true);
911       
912        }
913       
914
915
916group SetHeaders {
917
918
919        /**
920         *
921         * @desc function for setting of component variables related to message header fields
922         *              (message type independent: CSeq, contact, via), function uses information from userprofile
923         *             
924         * @param p_cSeq_s CSeq parameter
925         * @param p_method method name for cSeq header field
926         */     
927        function f_setHeadersGeneral(inout CSeq p_cSeq_s, in charstring p_method) runs on SipComponent
928        {
929          var SemicolonParam_List v_params;
930
931          p_cSeq_s.fieldName := CSEQ_E;
932          p_cSeq_s.seqNumber := p_cSeq_s.seqNumber + 1;
933          p_cSeq_s.method    := p_method ;
934          vc_cSeq := p_cSeq_s;
935     
936          vc_contact := valueof(m_Contact(m_SipUrl_contactIpaddr(vc_userprofile)));
937          vc_branch := c_branchCookie & f_getRndTag();
938          vc_via:={
939                fieldName := VIA_E,
940                viaBody          := {valueof(m_ViaBody_currIpaddr(vc_branch, vc_userprofile))}
941          };
942        }// end function f_setHeadersGeneral
943       
944        /**
945         *
946         * @desc setting of general and basic Bye header fields
947         *              in additon to the addresses (To, From, ReqUri)
948         * @param p_cSeq_s
949         */
950        function f_setHeadersBYE(inout CSeq p_cSeq_s) runs on SipComponent
951        {     
952          f_setHeadersGeneral(p_cSeq_s, "BYE"); // cseq, contact, branch, via
953
954          vc_callId := { fieldName:=CALL_ID_E, callid:=f_getRndCallId(p_cSeq_s) & c_AT & vc_userprofile.currIpaddr };
955
956          f_addTagInTo(vc_to);
957
958          vc_cancel_To := vc_to;
959          vc_caller_To := vc_to;
960     
961          vc_caller_From := vc_from;
962           
963          vc_reqHostPort := vc_requestUri.hostPort;
964     
965        }// end function f_setHeadersBYE
966
967        /**
968         *
969         * @desc function sets header field for the next outgoing REGISTER message
970         * @param p_cSeq_s CSeq parameter to be applied
971         */
972        function f_setHeaders_REGISTER(inout CSeq p_cSeq_s) runs on SipComponent
973        {
974          var SemicolonParam_List v_params;
975
976          f_setHeadersGeneral(p_cSeq_s, "REGISTER"); // cseq, contact, branch, via
977
978          vc_requestUri:=
979          {
980                scheme := c_sipScheme,
981                userInfo := omit,
982                hostPort := {host:=vc_userprofile.registrarDomain, portField:=omit},
983                urlParameters := omit,
984                headers := omit
985          };
986     
987          vc_reqHostPort := vc_requestUri.hostPort;
988     
989          vc_callId := { fieldName:=CALL_ID_E, callid:=f_getRndCallId(p_cSeq_s) & c_AT & vc_userprofile.currIpaddr };
990          vc_callIdReg := vc_callId;
991     
992          vc_to := valueof(m_To(m_SipUrl_currDomain(vc_userprofile)));
993          v_params := {{id:=c_tagId, paramValue:=f_getRndTag()}}
994          vc_from := {fieldName := FROM_E,
995                addressField :=vc_to.addressField,
996                fromParams := v_params
997          };
998         
999          if(not vc_firstREGISTER_sent)
1000          {
1001          v_params := {{id:=c_expiresId, paramValue:=c_shortRegistration}};
1002          vc_contact.contactBody.contactAddresses[0].contactParams := v_params;
1003          }
1004         
1005          vc_firstREGISTER_sent := true;//f_setHeaders_Register is called in deREGISTER function
1006         
1007          vc_authorization :=
1008          {
1009                fieldName := AUTHORIZATION_E,
1010                body := {f_calculatecCredentials_empty(vc_userprofile)}
1011          }
1012
1013     
1014        }// end function setHeaders_REGISTER
1015
1016        /**
1017         *
1018         * @desc function sets via, cseq and authorization header for the next outgoing (protected) REGISTER
1019         * @verdict
1020         */
1021        function f_setHeaders_2ndREGISTER() runs on SipComponent
1022        {
1023          var CommaParam_List v_challenge;
1024               
1025          vc_branch := c_branchCookie & f_getRndTag();
1026
1027          vc_via_REG :={
1028                fieldName := VIA_E,
1029                viaBody          := {valueof(m_ViaBody_currIpaddr(vc_branch, vc_userprofile))}
1030          };
1031         
1032          // Extract challenge and calculate credentials for a response.
1033          v_challenge := vc_response.msgHeader.wwwAuthenticate.challenge.otherChallenge.authParams;
1034                   
1035          // Increment CSeq sequence number
1036          vc_cSeq.seqNumber := vc_cSeq.seqNumber + 1;
1037     
1038      // Prepair right answer     
1039          vc_authorization :=
1040                   {
1041                         fieldName := AUTHORIZATION_E,
1042                         body := {f_calculatecCredentials(vc_userprofile, "REGISTER", v_challenge)}
1043                   }
1044                               
1045        }// end function f_setHeaders_2ndREGISTER
1046
1047        /**
1048         *
1049         * @desc function sets via, cseq and authorization header for the next outgoing (protected) REGISTER
1050         * NO response in Authorization header to cause an error
1051         * @verdict
1052         */
1053        function f_setHeaders_2ndREGISTER_wo_response() runs on SipComponent
1054        {
1055          var CommaParam_List v_challenge;
1056               
1057          vc_branch := c_branchCookie & f_getRndTag();
1058
1059          vc_via_REG :={
1060                fieldName := VIA_E,
1061                viaBody          := {valueof(m_ViaBody_currIpaddr(vc_branch, vc_userprofile))}
1062          };
1063         
1064          // Extract challenge and calculate credentials for a response.
1065          v_challenge := vc_response.msgHeader.wwwAuthenticate.challenge.otherChallenge.authParams;
1066                   
1067          // Increment CSeq sequence number
1068          vc_cSeq.seqNumber := vc_cSeq.seqNumber + 1;
1069     
1070          // Prepair right answer     
1071          vc_authorization :=
1072                   {
1073                         fieldName := AUTHORIZATION_E,
1074                         body := {f_calculatecCredentials_wo_response(vc_userprofile, "REGISTER", v_challenge)}
1075                   }
1076                               
1077        }// end function f_setHeaders_2ndREGISTER_wo_response
1078
1079        /**
1080         *
1081         * @desc function sets via, cseq and authorization header with different private name for the next outgoing (protected) REGISTER
1082         * @verdict
1083         */
1084        function f_setHeaders_2ndREGISTER_authorizationWithDifferentUserName() runs on SipComponent
1085        {
1086          var CommaParam_List v_challenge;
1087               
1088          vc_branch := c_branchCookie & f_getRndTag();
1089
1090          vc_via_REG :={
1091                fieldName := VIA_E,
1092                viaBody          := {valueof(m_ViaBody_currIpaddr(vc_branch, vc_userprofile))}
1093          };
1094         
1095          // Extract challenge and calculate credentials for a response.
1096          v_challenge := vc_response.msgHeader.wwwAuthenticate.challenge.otherChallenge.authParams;
1097                   
1098          // Increment CSeq sequence number
1099          vc_cSeq.seqNumber := vc_cSeq.seqNumber + 1;
1100     
1101      // Prepair right answer     
1102          vc_authorization :=
1103                   {
1104                         fieldName := AUTHORIZATION_E,
1105                         body := {f_calculatecCredentialsAndChangeUserName(vc_userprofile, "REGISTER", v_challenge)}
1106                   }
1107                               
1108        }// end function f_setHeaders_2ndREGISTER_authorizationWithDifferentUserName
1109
1110
1111        /**
1112         *
1113         * @desc function sets header fields for the next outgoing REGISTER (de-registration)
1114         * @param p_cSeq_s cSeq to be used
1115         * @verdict
1116         */
1117        function f_setHeaders_deREGISTER(inout CSeq p_cSeq_s) runs on SipComponent
1118        {
1119        f_setHeaders_REGISTER(p_cSeq_s);
1120        vc_contact :=
1121                {
1122                  fieldName := CONTACT_E,
1123                  contactBody := {wildcard := "*" }
1124                };
1125        } // end function f_setHeaders_deREGISTER
1126
1127
1128        /**
1129         *
1130         * @desc setting of general and basic Invite header fields
1131         *              in additon to the addresses (To, From, ReqUri)
1132         * @param p_cSeq_s
1133         */
1134        function f_setHeadersINVITE(inout CSeq p_cSeq_s) runs on SipComponent
1135        {     
1136          f_setHeadersGeneral(p_cSeq_s, "INVITE"); // cseq, contact, branch, via
1137
1138          vc_callId := { fieldName:=CALL_ID_E, callid:=f_getRndCallId(p_cSeq_s) & c_AT & vc_userprofile.currIpaddr };
1139
1140          vc_cancel_To := vc_to;
1141          vc_caller_To := vc_to;
1142     
1143          vc_caller_From := vc_from;
1144           
1145          vc_reqHostPort := vc_requestUri.hostPort;
1146     
1147        }// end function f_setHeadersINVITE
1148
1149        /**
1150         *
1151         * @desc setting of general and basic Message header fields
1152         *              in additon to the addresses (To, From, ReqUri)
1153         * @param p_cSeq_s
1154         */
1155        function f_setHeadersMESSAGE(inout CSeq p_cSeq_s) runs on SipComponent
1156        {     
1157          f_setHeadersGeneral(p_cSeq_s, "MESSAGE"); // cseq, contact, branch, via
1158
1159          vc_callId := { fieldName:=CALL_ID_E, callid:=f_getRndCallId(p_cSeq_s) & c_AT & vc_userprofile.currIpaddr };
1160
1161          vc_cancel_To := vc_to;
1162          vc_caller_To := vc_to;
1163     
1164          vc_caller_From := vc_from;
1165           
1166          vc_reqHostPort := vc_requestUri.hostPort;
1167     
1168        }// end function f_setHeadersMESSAGE
1169
1170        /**
1171                *
1172                * @desc setting of general and basic Notify header fields
1173                *               in additon to the addresses (To, From, ReqUri)
1174                * @param p_cSeq_s
1175                */
1176        function f_setHeadersNOTIFY(inout CSeq p_cSeq_s) runs on SipComponent
1177        {     
1178                        f_setHeadersGeneral(p_cSeq_s, "NOTIFY"); // cseq, contact, branch, via
1179
1180                        vc_callId := { fieldName:=CALL_ID_E, callid:=f_getRndCallId(p_cSeq_s) & c_AT & vc_userprofile.currIpaddr };
1181
1182                        vc_cancel_To := vc_to;
1183                        vc_caller_To := vc_to;
1184     
1185                        vc_caller_From := vc_from;
1186           
1187                        vc_reqHostPort := vc_requestUri.hostPort;
1188     
1189        }// end function f_setHeadersNOTIFY
1190
1191        /**
1192         *
1193         * @desc function sets header field for the next outgoing SUBSCRIBE message
1194         * @param p_cSeq_s CSeq parameter to be applied
1195         */
1196        function f_setHeaders_SUBSCRIBE(inout CSeq p_cSeq_s) runs on SipComponent
1197        {
1198          f_setHeadersGeneral(p_cSeq_s, "SUBSCRIBE"); // cseq, contact, branch, via
1199 
1200          vc_requestUri:=valueof(m_SipUrl_currDomain(vc_userprofile))
1201     
1202        }// end function setHeaders_SUBSCRIBE
1203       
1204        /**
1205                *
1206                * @desc setting of general and basic Subscribe header fields
1207                *               in additon to the addresses (To, From, ReqUri)
1208                * @param p_cSeq_s
1209                */
1210        function f_setHeadersSUBSCRIBE(inout CSeq p_cSeq_s) runs on SipComponent
1211        {     
1212                        f_setHeadersGeneral(p_cSeq_s, "SUBSCRIBE"); // cseq, contact, branch, via
1213
1214                        vc_callId := { fieldName:=CALL_ID_E, callid:=f_getRndCallId(p_cSeq_s) & c_AT & vc_userprofile.currIpaddr };
1215
1216                        vc_cancel_To := vc_to;
1217                        vc_caller_To := vc_to;
1218     
1219                        vc_caller_From := vc_from;
1220           
1221                        vc_reqHostPort := vc_requestUri.hostPort;
1222     
1223        }// end function f_setHeadersMESSAGE
1224       
1225        /**
1226         *
1227         * @desc setting of general and basic REFER header fields
1228         *              in additon to the addresses (To, From, ReqUri)
1229         * @param p_cSeq_s
1230         */
1231        function f_setHeadersREFER(inout CSeq p_cSeq_s) runs on SipComponent
1232        {     
1233          f_setHeadersGeneral(p_cSeq_s, "REFER"); // cseq, contact, branch, via
1234
1235          vc_callId := { fieldName:=CALL_ID_E, callid:=f_getRndCallId(p_cSeq_s) & c_AT & vc_userprofile.currIpaddr };
1236
1237          vc_cancel_To := vc_to;
1238          vc_caller_To := vc_to;
1239     
1240          vc_caller_From := vc_from;
1241           
1242          vc_reqHostPort := vc_requestUri.hostPort;
1243     
1244        }// end function f_setHeadersREFER
1245
1246        /**
1247         *
1248         * @desc This function reads all necessary headers from the received REGISTER message and generate the tag for the answer
1249         * @param p_Request REGISTER that has been received
1250         */
1251        function f_setHeadersOnReceiptOfREGISTER(Request p_Request)
1252        runs on SipComponent {
1253
1254          f_setHeadersOnReceiptOfRequest(p_Request);
1255       
1256          vc_callId := p_Request.msgHeader.callId;
1257          vc_caller_From := vc_from;
1258          f_addTagInTo(vc_to);
1259          vc_caller_To := vc_to;
1260          vc_requestUri := p_Request.requestLine.requestUri;
1261     
1262          vc_cancel_To := p_Request.msgHeader.toField;
1263     
1264          if (ispresent(p_Request.msgHeader.contact)) {
1265                vc_reqHostPort := f_getContactAddr(p_Request.msgHeader.contact.contactBody.contactAddresses[0]);
1266                }
1267     
1268          // update callee information and pick up tag if the call need to be canceled
1269          vc_callee_To := {fieldName := TO_E,
1270                addressField := vc_caller_From.addressField,
1271                toParams := vc_caller_From.fromParams};
1272     
1273          vc_callee_From := {fieldName := FROM_E,
1274                addressField := vc_caller_To.addressField,
1275                fromParams := vc_caller_To.toParams};
1276     
1277        } // end f_setHeadersOnReceiptOfREGISTER
1278
1279        /**
1280         *
1281         * @desc This function reads all necessary headers from the received SUBSCRIBE message and generate the tag for the answer
1282         * @param p_Request SUBSCRIBE that has been received
1283         */
1284        function f_setHeadersOnReceiptOfSUBSCRIBE(Request p_Request)
1285        runs on SipComponent {
1286
1287          f_setHeadersOnReceiptOfRequest(p_Request);
1288       
1289          vc_callId := p_Request.msgHeader.callId;
1290          vc_caller_From := vc_from;
1291          f_addTagInTo(vc_to);
1292          vc_caller_To := vc_to;
1293          vc_requestUri := p_Request.requestLine.requestUri;
1294     
1295          vc_cancel_To := p_Request.msgHeader.toField;
1296     
1297          if (ispresent(p_Request.msgHeader.contact)) {
1298                vc_reqHostPort := f_getContactAddr(p_Request.msgHeader.contact.contactBody.contactAddresses[0]);
1299                }
1300     
1301          // update callee information and pick up tag if the call need to be canceled
1302          vc_callee_To := {fieldName := TO_E,
1303                addressField := vc_caller_From.addressField,
1304                toParams := vc_caller_From.fromParams};
1305     
1306          vc_callee_From := {fieldName := FROM_E,
1307                addressField := vc_caller_To.addressField,
1308                fromParams := vc_caller_To.toParams};
1309     
1310        } // end f_setHeadersOnReceiptOfSUBSCRIBE
1311   
1312        /**
1313         *
1314         * @desc function reads all necessary headers from
1315         * the received INVITE message and generate the tag for the answer
1316         * @param p_Request received INVITE message
1317         * @verdict
1318         */
1319        function f_setHeadersOnReceiptOfINVITE(Request p_Request) runs on SipComponent {
1320
1321        f_setHeadersOnReceiptOfRequest(p_Request);
1322
1323        vc_callId := p_Request.msgHeader.callId;
1324
1325        vc_requestUri := p_Request.requestLine.requestUri;
1326     
1327        vc_cancel_To := p_Request.msgHeader.toField;
1328        f_addTagInTo(vc_to);
1329        vc_caller_From := vc_from;
1330        vc_caller_To := vc_to;
1331     
1332        if (ispresent(p_Request.msgHeader.contact)) {
1333                vc_reqHostPort :=
1334                f_getContactAddr(p_Request.msgHeader.contact.contactBody.contactAddresses[0]);
1335                };
1336     
1337         // update callee information and pick up tag if the call need to be canceled
1338        vc_callee_To := {fieldName := TO_E,
1339           addressField := vc_caller_From.addressField,
1340           toParams := vc_caller_From.fromParams};
1341     
1342        vc_callee_From := {fieldName := FROM_E,
1343           addressField := vc_caller_To.addressField,
1344           fromParams := vc_caller_To.toParams};
1345       
1346        if (ispresent(p_Request.msgHeader.privacy)) {
1347                vc_privacy := p_Request.msgHeader.privacy;
1348                };
1349       
1350        if (ispresent(p_Request.messageBody)) {
1351                //cleaning of attributes before assignment
1352                if (ispresent(vc_sdp_remote.media_list))
1353                {
1354                                for (var integer i:=0; i<sizeof(vc_sdp_remote.media_list); i:=i+1)
1355                                {                       
1356                                                if (ispresent(vc_sdp_remote.media_list[i].attributes))
1357                                                {
1358                                                        for (var integer j:=0; j<sizeof(vc_sdp_remote.media_list[i].attributes); j:=j+1)
1359                                                        {                       
1360                                        vc_sdp_remote.media_list[i].attributes := omit ;
1361                                                        }
1362                                                }
1363                                };
1364                }               
1365               
1366                // save SDP if present
1367                if ( ischosen(p_Request.messageBody.sdpMessageBody))
1368                {
1369                        vc_sdp_remote := p_Request.messageBody.sdpMessageBody;           
1370                        vc_sdp_remote_is_valid := true;
1371                        f_prepare_SDP_answer();                                         
1372                };
1373               
1374                // save XML if present
1375                if ( ischosen(p_Request.messageBody.xmlBody))
1376                {
1377                        vc_xml_remote := p_Request.messageBody.xmlBody;                                 
1378                }
1379
1380                if ( ischosen(p_Request.messageBody.mimeMessageBody))
1381                {
1382                       
1383                        for (var integer j:=0; j<sizeof(p_Request.messageBody.mimeMessageBody.mimeEncapsulatedList); j:=j+1){
1384                                if (match(p_Request.messageBody.mimeMessageBody.mimeEncapsulatedList[j].content_type,c_sdpAplication))
1385                                {
1386                                        vc_sdp_remote := p_Request.messageBody.mimeMessageBody.mimeEncapsulatedList[j].mime_encapsulated_part.sdpMessageBody;
1387                                        vc_sdp_remote_is_valid := true;
1388                                        f_prepare_SDP_answer();
1389                                };
1390                                if (match(p_Request.messageBody.mimeMessageBody.mimeEncapsulatedList[j].content_type,c_xmlAplication))
1391                                {
1392                                        vc_xml_remote := p_Request.messageBody.mimeMessageBody.mimeEncapsulatedList[j].mime_encapsulated_part.xmlBody;
1393                                };                     
1394                        }       
1395                }       
1396        };
1397           
1398        if (ispresent(p_Request.msgHeader.supported.optionsTags)) {
1399                for (var integer i := sizeof(p_Request.msgHeader.supported.optionsTags); i>0; i:=i-1)
1400                   {
1401                           if (p_Request.msgHeader.supported.optionsTags[i-1]=="100rel")
1402                           { vc_supported_100rel := true };
1403                           if (p_Request.msgHeader.supported.optionsTags[i-1]=="precondition")
1404                           { vc_supported_precondition := true }
1405                   }
1406                };
1407     
1408   } // end f_setHeadersOnReceiptOfINVITE
1409
1410        /**
1411         *
1412         * @desc function reads header field of a received BYE message
1413         * @param p_Request received BYE
1414         */
1415   function f_setHeadersOnReceiptOfBYE(Request p_BYE_Request)
1416   runs on SipComponent
1417   {
1418       
1419         f_setHeadersOnReceiptOfRequest(p_BYE_Request);
1420         vc_callId := p_BYE_Request.msgHeader.callId;
1421
1422   } // end f_setHeadersOnReceiptOfBYE
1423
1424        /**
1425         *
1426         * @desc function reads header field from an incoming Request message
1427         * @param p_Request received Request message
1428         */
1429        function f_setHeadersOnReceiptOfRequest(Request p_Request) runs on SipComponent {
1430     vc_request := p_Request;
1431         vc_cSeq := p_Request.msgHeader.cSeq;
1432         vc_iut_CSeq  := p_Request.msgHeader.cSeq;
1433         vc_from := p_Request.msgHeader.fromField;
1434         vc_to := p_Request.msgHeader.toField;
1435         vc_via := p_Request.msgHeader.via;
1436         // update sent_label according to received via header field
1437         f_getViaReplyAddr(vc_via.viaBody, vc_sent_label);
1438         
1439         // Catch route
1440         vc_boo_recordRoute:=false;
1441         
1442         if (ispresent(p_Request.msgHeader.recordRoute))
1443         {
1444           vc_boo_recordRoute:=true;
1445           vc_recordRoute := p_Request.msgHeader.recordRoute;
1446         }
1447        } // end f_setHeadersOnReceiptOfRequest
1448
1449        /**
1450         *
1451         * @desc functions reads header fields from an incoming Response message
1452         * @param p_cSeq
1453         * @param p_response received response message
1454         * @verdict
1455         */
1456    function f_setHeadersOnReceiptOfResponse(inout CSeq p_cSeq, Response p_response) runs on SipComponent
1457   {
1458         var integer v_i, v_j, v_nbroute;
1459         var Contact v_contact; //only for local purpose
1460               
1461         vc_response := p_response;
1462         //vc_cSeq := p_cSeq; //must not save global c_seq because it can overwrite temporary cSeq
1463         vc_to :=p_response.msgHeader.toField;
1464         vc_from :=p_response.msgHeader.fromField;
1465         vc_caller_To := vc_to;
1466         vc_caller_From := vc_from;
1467     
1468         if (ispresent(p_response.msgHeader.contact))
1469         {
1470           v_contact := p_response.msgHeader.contact;
1471           if (ischosen(v_contact.contactBody.contactAddresses))
1472           {
1473                 vc_reqHostPort := f_getContactAddr(v_contact.contactBody.contactAddresses[0]);
1474           }
1475         }
1476         else
1477         {
1478           if (ischosen(vc_to.addressField.nameAddr))
1479           {
1480                 vc_reqHostPort := vc_to.addressField.nameAddr.addrSpec.hostPort;
1481           }
1482           else
1483           {
1484                 vc_reqHostPort := vc_to.addressField.addrSpecUnion.hostPort;
1485           }
1486         }
1487     
1488         vc_callee_To:={fieldName := TO_E,
1489           addressField := vc_caller_From.addressField,
1490           toParams := vc_caller_From.fromParams};
1491     
1492         vc_callee_From:= {fieldName := FROM_E,
1493           addressField := vc_caller_To.addressField,
1494           fromParams := vc_caller_To.toParams};
1495         
1496         vc_via:= p_response.msgHeader.via;
1497     
1498         // Route Management
1499         if (ispresent(p_response.msgHeader.recordRoute))
1500         {
1501           vc_recordRoute := p_response.msgHeader.recordRoute;
1502           v_nbroute := sizeof(vc_recordRoute.routeBody);
1503           // copy and reverse the order of the routes in route header
1504           for (v_i:=0; v_i<=(v_nbroute - 1); v_i:=v_i+1)
1505           {
1506                 v_j:= v_nbroute - 1 - v_i;
1507                 vc_route.routeBody[v_j]:=vc_recordRoute.routeBody[v_i];
1508           }
1509           vc_route.fieldName := ROUTE_E;
1510           vc_boo_recordRoute := true;
1511           vc_boo_route := true;
1512         }
1513         else
1514         {
1515           vc_boo_recordRoute := false;
1516           vc_boo_route := false;
1517         };
1518
1519
1520         // extentions due to new fields in PRACK and UPDATE messages
1521         if (ispresent(p_response.msgHeader.rSeq)) {
1522                vc_rAck :=
1523                         { fieldName := RACK_E,
1524                           responseNum := valueof(p_response.msgHeader.rSeq.responseNum),
1525                           seqNumber := valueof(p_response.msgHeader.cSeq.seqNumber),
1526                           method := valueof(p_response.msgHeader.cSeq.method)
1527                         };
1528                 };
1529
1530         // extentions due to new HistoryInfo fields 180 or 200OK messages
1531         if (ispresent(p_response.msgHeader.historyInfo)) {
1532                vc_historyInfoList := valueof(p_response.msgHeader.historyInfo.historyInfoList);
1533                vc_history_is_valid := true
1534                }
1535           else {vc_history_is_valid := false};
1536
1537         //sdpMessageBody answer
1538         if (ispresent(p_response.messageBody)) {
1539                if ( ischosen(p_response.messageBody.sdpMessageBody))
1540                {
1541                        vc_sdp_remote := p_response.messageBody.sdpMessageBody;           
1542                        vc_sdp_remote_is_valid := true;
1543                }
1544
1545                if ( ischosen(p_response.messageBody.xmlBody))
1546                {
1547                        vc_xml_remote := p_response.messageBody.xmlBody;                                       
1548                }
1549
1550                if ( ischosen(p_response.messageBody.mimeMessageBody))
1551                {
1552                       
1553                        for (var integer j:=0; j<sizeof(p_response.messageBody.mimeMessageBody.mimeEncapsulatedList); j:=j+1){
1554                                if (match(p_response.messageBody.mimeMessageBody.mimeEncapsulatedList[j].content_type,c_sdpAplication))
1555                                {
1556                                        vc_sdp_remote := p_response.messageBody.mimeMessageBody.mimeEncapsulatedList[j].mime_encapsulated_part.sdpMessageBody;
1557                                };
1558                                if (match(p_response.messageBody.mimeMessageBody.mimeEncapsulatedList[j].content_type,c_xmlAplication))
1559                                {
1560                                        vc_xml_remote := p_response.messageBody.mimeMessageBody.mimeEncapsulatedList[j].mime_encapsulated_part.xmlBody;
1561                                };                     
1562                        }       
1563                }
1564         };
1565
1566   }// end function f_setHeadersOnReceiptOfResponse
1567
1568   /**
1569        *
1570        * @desc functions reads ServiceRoute header field from an incoming 200 Response message in registration
1571        * @param p_cSeq
1572        * @param p_response received response message
1573        */
1574    function f_getServiceRouteMapIntoRouteInRegistration(inout CSeq p_cSeq, Response p_response) runs on SipComponent
1575   {
1576         var integer v_i, v_j, v_nbroute;
1577         var ServiceRoute v_serviceRoute;
1578               
1579         // Route Management
1580         if (ispresent(p_response.msgHeader.serviceRoute))
1581         {
1582           v_serviceRoute := p_response.msgHeader.serviceRoute;
1583           v_nbroute := sizeof(v_serviceRoute.routeBody);
1584           // copy and reverse the order of the routes in route header
1585           for (v_i:=0; v_i<=(v_nbroute - 1); v_i:=v_i+1)
1586           {
1587                 v_j:= v_nbroute - 1 - v_i;
1588                 vc_route.routeBody[v_j]:=v_serviceRoute.routeBody[v_i];
1589           }
1590           vc_route.fieldName := ROUTE_E;
1591         }
1592
1593   }// end function f_getServiceRouteMapIntoRouteInRegistration
1594
1595
1596} // end group SetHeaders
1597   
1598} // end group FieldOperations
1599
1600group SDPOperations{
1601       
1602        /**
1603        *  @desc check if message body include SDP attribute (2nd parameter)
1604        *        for any media
1605        *               
1606        */
1607        function f_check_attribute(in SDP_Message p_sdp, in template SDP_attribute p_attribute) runs on SipComponent return boolean {
1608               
1609        if (ispresent(p_sdp.media_list)) {
1610                for (var integer j:=0; j<sizeof(p_sdp.media_list); j:=j+1){                     
1611                        if (ispresent(p_sdp.media_list[j].attributes)) {
1612                                for (var integer i:=0; i<sizeof(p_sdp.media_list[j].attributes); i:=i+1){                       
1613                                        if (match(p_sdp.media_list[j].attributes[i],p_attribute))
1614                                                {return(true);};
1615                                        };
1616                        }
1617                        };
1618        }
1619        if (ispresent(p_sdp.attributes)) {
1620                for (var integer j:=0; j<sizeof(p_sdp.attributes); j:=j+1){                     
1621                        if (match(p_sdp.attributes[j],p_attribute)) {return(true);};
1622                        };
1623        }
1624       
1625        return(false);
1626        }               
1627       
1628        /**
1629         *
1630         * @desc        identify an SDP direction attribute (session or first media attribute) in a SDP message and return its answer value
1631         * @param       p_sdp           the SDP message that has been received
1632         * @param       p_attribute incoming SDP attribute that need to be used for the SDP direction (answer)
1633         * @return      the new attribute (to be send out) derived from the incoming SDP value
1634         * @verdict
1635         */
1636        function f_get_attribute_answer(in SDP_Message p_sdp, in template SDP_attribute p_attribute) runs on SipComponent return SDP_attribute {
1637
1638                var template SDP_attribute v_attribute := p_attribute;
1639               
1640                // check if the selected attribute is included in the SDP offer (session attributes)
1641                if (ispresent(p_sdp.attributes)) {
1642                        for (var integer j:=0; j<sizeof(p_sdp.attributes); j:=j+1){                     
1643                                if (match(p_sdp.attributes[j],p_attribute)) {v_attribute := p_sdp.attributes[j];};
1644                                };
1645                }
1646
1647                // check if the selected attribute is included in the SDP offer (any of the media attributes)
1648                if (ispresent(p_sdp.media_list)) {
1649                        for (var integer j:=0; j<sizeof(p_sdp.media_list); j:=j+1){                     
1650                                if (ispresent(p_sdp.media_list[j].attributes)) {
1651                                        for (var integer i:=0; i<sizeof(p_sdp.media_list[j].attributes); i:=i+1){                       
1652                                                if (match(p_sdp.media_list[j].attributes[i],p_attribute))
1653                                                        {v_attribute := p_sdp.media_list[j].attributes[i];};
1654                                                };
1655                                }
1656                                };
1657                }
1658                select (valueof(v_attribute))
1659                {
1660                        case (mw_attribute_sendonly) {return(valueof(m_attribute_recvonly));}
1661                        case (mw_attribute_sendrecv) {return(valueof(m_attribute_sendrecv));}//MRO     
1662                        case (mw_attribute_inactive) {return(valueof(m_attribute_inactive));}//MRO
1663                        case (mw_attribute_recvonly) {return(valueof(m_attribute_sendonly));}//MRO
1664                }
1665                return(valueof(m_attribute_sendrecv));//the default return value in case of missing attribute offer 
1666        }
1667
1668        /**
1669        *  @desc check if message body include SDP bandwidth (2nd parameter)
1670        *                either for the session or a media description
1671        */
1672        function f_check_bandwidth(in SDP_Message loc_sdp, in template SDP_bandwidth loc_bandw) runs on SipComponent return boolean {
1673       
1674                                        if (ispresent(loc_sdp.bandwidth)) {
1675                                                for (var integer j:=0; j<sizeof(loc_sdp.bandwidth); j:=j+1){                   
1676                                                        if (match(loc_sdp.bandwidth[j],loc_bandw)) {return(true);};
1677                                                        };
1678                                        };
1679                                        if (ispresent(loc_sdp.media_list)) {
1680                                                for (var integer j:=0; j<sizeof(loc_sdp.media_list); j:=j+1){
1681                                                        if (ispresent(loc_sdp.media_list[j].bandwidth)) {                                               
1682                                                                if (match(loc_sdp.media_list[j].bandwidth,loc_bandw)) {return(true);};
1683                                                                };
1684                                                        };
1685                                        };
1686       
1687                return(false);
1688        }
1689
1690        /**
1691        *  @desc check if message body include SDP media (2nd parameter)
1692        *               
1693        */
1694        function f_check_media(in SDP_Message loc_sdp, in template SDP_media_desc loc_media) runs on SipComponent return boolean {
1695               
1696        if (ispresent(loc_sdp.media_list)) {
1697                for (var integer j:=0; j<sizeof(loc_sdp.media_list); j:=j+1){                   
1698                        if (match(loc_sdp.media_list[j].media_field.transport,loc_media.media_field.transport) and
1699                                match(loc_sdp.media_list[j].media_field.fmts,loc_media.media_field.fmts))
1700                                {return(true);};
1701                        };
1702        }
1703        return(false);
1704        }
1705       
1706        /**
1707         * @desc
1708         *     check if message body include precondition mechanism (a=des and
1709         *     a=curr) retrun true, else false
1710         * @param loc_sdp SDP message
1711         */
1712        function f_check_precondition(in SDP_Message loc_sdp) runs on SipComponent return boolean {
1713        if (f_check_attribute(loc_sdp, mw_attribute_des) or
1714                f_check_attribute(loc_sdp, mw_attribute_curr))
1715                {return(true);}
1716               
1717        return(false);
1718        }       
1719                       
1720
1721        /**
1722        *  @desc check if message body include SDP media direction return true, else false
1723        *               
1724        */
1725        function f_check_media_direction(in SDP_Message loc_sdp) runs on SipComponent return boolean {
1726               
1727        if (f_check_attribute(loc_sdp, mw_attribute_sendonly) or
1728                f_check_attribute(loc_sdp, mw_attribute_recvonly) or
1729                f_check_attribute(loc_sdp, mw_attribute_sendrecv) or
1730                f_check_attribute(loc_sdp, mw_attribute_inactive))
1731                {return(true);}
1732               
1733        return(false);
1734        }               
1735
1736        /**
1737        *  @desc copy media/attribute lines from remote to local SDP variable
1738        *               
1739        */
1740        function f_check_SDP(integer loc_sdp, integer loc_codec) runs on SipComponent
1741        return boolean
1742        {
1743                var SDP_media_desc v_media := f_prepare_media(loc_sdp,loc_codec);
1744                log("log0");
1745                if (vc_sdp_remote.media_list[0].media_field.media != v_media.media_field.media)
1746                        { log("log1"); return false };
1747                if (vc_sdp_remote.media_list[0].media_field.transport != v_media.media_field.transport)
1748                        { log("log2"); return false };
1749                if (vc_sdp_remote.media_list[0].media_field.fmts != v_media.media_field.fmts)
1750                        { log("remote:",vc_sdp_remote.media_list[0].media_field.fmts,"expect:",v_media.media_field.fmts); return false };
1751                       
1752                return true
1753        }
1754       
1755        /**
1756         * @desc replace the first curr media attribute with the given value.
1757         * @param p_sdp SDP message to modify
1758         * @param p_curr new curr attribute
1759         */
1760        function f_replace_curr_attribute(inout SDP_Message p_sdp, in SDP_attribute_curr p_curr) {
1761                if(ispresent(p_sdp.media_list)) {
1762                        var integer mn := sizeof(p_sdp.media_list[0].attributes);
1763                        for(var integer i := 0; i<=mn; i := i+1) {
1764                                if(ischosen(p_sdp.media_list[0].attributes[i].curr)){
1765                                        p_sdp.media_list[0].attributes[i].curr := p_curr;
1766                                        i:=mn;
1767                                }       
1768                        }
1769                }
1770        }
1771       
1772        /**
1773         * @desc append new media attribute to the first media description.
1774         * @param p_sdp SDP message to modify
1775         * @param p_att SDP attribute to appand
1776         */
1777        function f_append_media_attribute(inout SDP_Message p_sdp, in SDP_attribute p_att) {
1778                if(ispresent(p_sdp.media_list)) {
1779                        var integer mn := sizeof(p_sdp.media_list[0].attributes);
1780                        p_sdp.media_list[0].attributes[mn] := p_att;
1781                }
1782        }
1783       
1784       
1785        /**
1786        *  @desc append new media to the existing media list in SDP
1787        *               
1788        */
1789        function f_append_media(inout SDP_Message loc_SDP, in template SDP_media_desc loc_media)
1790        {
1791                var integer mn := sizeof(loc_SDP.media_list);
1792                loc_SDP.media_list[mn] := valueof(loc_media);
1793        }
1794       
1795        /**
1796        *  @desc repare media/attribute lines
1797        *               
1798        */
1799        function f_prepare_media(integer loc_sdp, integer loc_codec) runs on SipComponent
1800        return SDP_media_desc
1801        {
1802                var charstring v_codecs[32] := {
1803                        "PCMU/8000", "GSM/8000", "G723/8000", "DVI4/8000",
1804                        "DVI4/16000", "LPC/8000", "PCMA/8000", "G722/8000",
1805                        "L16/44100/2", "L16/44100", "QCELP/8000", "CN/8000",
1806                        "MPA/90000", "G728/8000", "DVI4/11025", "DVI4/22050",
1807                        "G729/8000", "G726-40/8000", "G726-32/8000", "G726-24/8000",
1808                        "G726-16/8000", "G726D/8000", "G726E/8000", "GSM-EFR/8000",
1809                        "CelB/90000", "JPEG/90000", "Nv/90000", "H261/90000",
1810                        "MPV/90000", "MP2T/90000", "H263/90000", "H263-1998/90000"
1811                }
1812                var SDP_media_desc v_media :=
1813                        {
1814                                media_field := {
1815                                        media := "audio",
1816                                        ports := {
1817                                                port_number := 10000,
1818                                                num_of_ports:=omit },
1819                                        transport := "RTP/AVP",
1820                                        fmts := { "0" }
1821                                }, //m=audio 8500 RTP/AVP 0
1822                                information := omit,
1823                                connections := omit,
1824                                bandwidth := omit,
1825                                key := omit,                                           
1826                                attributes := omit
1827                        };
1828                       
1829                if (32<loc_codec or loc_codec<1) {
1830                        log("Unexpected SDP variant");
1831                        setverdict(inconc);
1832                        return (v_media)}
1833
1834                if (loc_sdp == 1) {}
1835                else if (loc_sdp == 2) {
1836                        v_media.media_field.fmts := {PX_SIP_SDP_dyn}; //{ "98", "0" };
1837                        v_media.attributes := {{
1838                        rtpmap := { attr_value := PX_SIP_SDP_dyn & " " & v_codecs[loc_codec-1] } // PX_SIP_SDP_dyn := 98
1839                        }}
1840                } else if (loc_sdp == 3) {
1841                        v_media.media_field.fmts := { "8" }
1842                } else if (loc_sdp == 4) {
1843                        v_media.media_field.fmts := { "99", "8" };
1844                        v_media.attributes := {{
1845                                rtpmap := { attr_value := "99 " & v_codecs[loc_codec-1] }
1846                                                }}
1847                } else if (loc_sdp == 5) {
1848                        v_media.media_field.media := "image";
1849                        v_media.media_field.transport := "udptl";
1850                        v_media.media_field.fmts := { "t38" }
1851                } else if (loc_sdp == 6) {
1852                        v_media.media_field.media := "image";
1853                        v_media.media_field.transport := "tcptl";
1854                        v_media.media_field.fmts := { "t38" }
1855                } else {
1856                        log("Unexpected SDP variant"); setverdict(inconc)
1857                };
1858                       
1859                return (v_media);
1860        }
1861
1862        /**
1863        *  @desc repare media/attribute lines
1864        *               
1865        */
1866        function f_prepare_SDP(integer loc_sdp, integer loc_codec) runs on SipComponent
1867        {
1868
1869                vc_sdp_local.media_list := {f_prepare_media(loc_sdp,loc_codec)};
1870        }
1871       
1872        /**
1873        *
1874        * @desc function that copy media/attribute lines from remote to local SDP variable
1875        */
1876        function f_prepare_SDP_answer() runs on SipComponent
1877        {
1878                var integer mn, cn := 0, i, j, k :=0;
1879                var charstring v_PT, v_rtpmap := "";
1880                var SDP_attribute_list v_mediaAttributes := {};
1881                //increase session version
1882                vc_sdp_local.origin.session_version :=  int2str(str2int(vc_sdp_local.origin.session_version)+1);
1883                // if more than one codec, select the firs one
1884                mn:= sizeof(vc_sdp_local.media_list);
1885                for (i :=0;  i < mn; i := i+1)
1886                {
1887                        //for every single media
1888                        if (ispresent(vc_sdp_local.media_list[i].attributes))
1889                        {
1890                                cn := sizeof(vc_sdp_local.media_list[i].attributes);
1891                        };
1892                        if (sizeof(vc_sdp_local.media_list[i].media_field.fmts)>1)
1893                        {
1894                                // select the first one
1895                                v_PT := vc_sdp_local.media_list[i].media_field.fmts[0];
1896                                vc_sdp_local.media_list[i].media_field.fmts := {v_PT};
1897                                for (j :=0; j<cn; j:=j+1)
1898                                {
1899                                        if (ischosen(vc_sdp_local.media_list[i].attributes[j].rtpmap))
1900                                        {
1901                                                if (v_PT == regexp(vc_sdp_local.media_list[i].attributes[j].rtpmap.attr_value,  "[ \t]#(0,)([/d]+)*",   0))
1902                                                {
1903                                                        v_rtpmap := vc_sdp_local.media_list[i].attributes[j].
1904                                                        rtpmap.attr_value;
1905                                                        v_mediaAttributes[k] := {rtpmap := {attr_value := v_rtpmap}};
1906                                                        k := k+1;
1907                                                } // else line is not copied
1908                                        }
1909
1910
1911                                        // simplified handling of status attributes (copy/keep status from peer):
1912                                        // a) copy/keep SDP_attribute_curr (invert tags if applicable)
1913                                        if (ischosen(vc_sdp_local.media_list[i].attributes[j].curr))
1914                                        {
1915                                                // invert local/remote status tags
1916                                                if (vc_sdp_local.media_list[i].attributes[j].curr.statusType == "local")
1917                                                        {vc_sdp_local.media_list[i].attributes[j].curr.statusType := "remote"};
1918                                                if (vc_sdp_local.media_list[i].attributes[j].curr.statusType == "remote")
1919                                                        {vc_sdp_local.media_list[i].attributes[j].curr.statusType := "local"};
1920                                                // invert send/recv direction tags
1921                                                if (vc_sdp_local.media_list[i].attributes[j].curr.direction == "send")
1922                                                        {vc_sdp_local.media_list[i].attributes[j].curr.direction := "recv"};
1923                                                if (vc_sdp_local.media_list[i].attributes[j].curr.direction == "recv")
1924                                                        {vc_sdp_local.media_list[i].attributes[j].curr.direction := "send"};
1925                                        }                               
1926                                        // b) copy/keep SDP_attribute_des (keep strength, invert tags if applicable)   
1927                                        else if (ischosen(vc_sdp_local.media_list[i].attributes[j].des))
1928                                        {
1929                                                // invert local/remote status tags
1930                                                if (vc_sdp_local.media_list[i].attributes[j].des.statusType == "local")
1931                                                        {vc_sdp_local.media_list[i].attributes[j].des.statusType := "remote"};
1932                                                if (vc_sdp_local.media_list[i].attributes[j].des.statusType == "remote")
1933                                                        {vc_sdp_local.media_list[i].attributes[j].des.statusType := "local"};
1934                                                // invert send/recv direction tags
1935                                                if (vc_sdp_local.media_list[i].attributes[j].des.direction == "send")
1936                                                        {vc_sdp_local.media_list[i].attributes[j].des.direction := "recv"};
1937                                                if (vc_sdp_local.media_list[i].attributes[j].des.direction == "recv")
1938                                                        {vc_sdp_local.media_list[i].attributes[j].des.direction := "send"};
1939                                        }                               
1940                                        // c) simplification: assume no SDP_attribute_conf     
1941                                        else if (ischosen(vc_sdp_local.media_list[i].attributes[j].conf))
1942                                        {
1943                                                // todo: handle SDP_attribute_conf
1944                                        }                                       
1945                                               
1946                                         
1947                                        else
1948                                        {
1949                                                // simple copy of attribute
1950                                                v_mediaAttributes[k] := vc_sdp_local.media_list[i].attributes[j];
1951                                                k := k+1;
1952                                        }
1953                                }
1954                                vc_sdp_local.media_list[i].attributes := v_mediaAttributes;
1955                        }
1956                }
1957                // add handling of prenegotiation, change ports if required etc.
1958                //if prenegotiation...
1959        }
1960
1961        /**
1962        *  @desc reject SDP offer by setting media ports to 0
1963        *               
1964        */
1965        function f_reject_SDP_offer() runs on SipComponent
1966        {
1967                var integer mn, i;
1968                f_copy_SDP(); // TO BE DONE with more details!
1969                //increase session version
1970                vc_sdp_local.origin.session_version := int2str(str2int(vc_sdp_local.origin.session_version)+1);
1971                // if more than one codec, select the firs one
1972                mn:= sizeof(vc_sdp_local.media_list);
1973                for (i :=0;  i < mn; i := i+1)
1974                {
1975                        vc_sdp_local.media_list[i].media_field.ports := {0, omit};
1976                        vc_sdp_local.media_list[i].attributes := omit; //{};
1977                };
1978        }
1979
1980        /**
1981         *
1982         * @desc        copies SDP message elements from remote to local component variable:
1983         *                              - bandwidth
1984         *                              - session version (will be incremented)
1985         *                              - media list
1986         *                      modify the direction attribute of an SDP media list entry within an SDP message (vc_sdp_local)
1987         * @param       p_medianum              list position number of the media (if value 0 identifies first media list element)
1988         * @param       p_direction             the new direction attribute to be included in the media entry
1989         * @verdict
1990         */
1991        function f_SIP_modMediaDirection(integer p_medianum, template SDP_attribute p_direction) runs on SipComponent
1992        {
1993                var boolean v_set_direction; // flag indicates if direction attribute has been modified
1994                var integer v_mn := 0;           // length of media list (number of entries)
1995                var integer v_cn := 0;           // number of attributes of a media entry
1996                var integer i, j, k := 0;
1997                var SDP_attribute_list v_mediaAttributes := {}; // collect the media attributes (to be assigned at end of function)
1998               
1999                f_copy_SDP(); // copy SDP session bandwidth and media list from remote to local component variable
2000               
2001                // increment session version
2002                vc_sdp_local.origin.session_version := int2str(str2int(vc_sdp_local.origin.session_version)+1);
2003               
2004                // if more than one codec, select the first one
2005                v_mn:= sizeof(vc_sdp_local.media_list);
2006
2007                if (p_medianum == 0) //specific media requested
2008                {
2009                        p_medianum := 1; // start checking from first media
2010                };
2011                if (p_medianum > 0) //specific media requested
2012                {
2013                        if (not(p_medianum > v_mn))
2014                                {v_mn := p_medianum}
2015                };
2016               
2017                // handling of media list elements
2018                for (i :=0;  i < v_mn; i := i+1)
2019                {
2020                        v_cn := 0; // initialize the number of attributes of the media list entry
2021               
2022                        if (ispresent(vc_sdp_local.media_list)) //media_list is optional
2023                        {                                               
2024//                              log("vc_sdp_local.media_list[i] ",vc_sdp_local.media_list[i]);
2025                                if (ispresent(vc_sdp_local.media_list[i].attributes))
2026                                {
2027                                        v_cn := sizeof(vc_sdp_local.media_list[i].attributes);
2028                                };
2029                               
2030                                v_set_direction := false;
2031                               
2032                                //if (sizeof(vc_sdp_local.media_list[i].media_field.fmts)>1)
2033                                // select the first one
2034                                for (j :=0; j<v_cn; j:=j+1)
2035                                {
2036                                        if (ischosen(vc_sdp_local.media_list[i].attributes[j].recvonly)
2037                                                        or ischosen(vc_sdp_local.media_list[i].attributes[j].sendonly)
2038                                                        or ischosen(vc_sdp_local.media_list[i].attributes[j].inactive)
2039                                                        or ischosen(vc_sdp_local.media_list[i].attributes[j].sendrecv))
2040                                                {
2041                                                        v_mediaAttributes[k] := valueof(p_direction);
2042                                                        v_set_direction := true;
2043                                                }
2044                                                else // non-direction attributes will be copied
2045                                                {
2046                                                        v_mediaAttributes[k] := vc_sdp_local.media_list[i].attributes[j];
2047                                                        k := k+1;
2048                                                }
2049                                }
2050                               
2051                                if (not v_set_direction)
2052                                        { v_mediaAttributes[k] := valueof(p_direction)};
2053                                vc_sdp_local.media_list[i].attributes := v_mediaAttributes;
2054                               
2055                                // }
2056                        }
2057                }       
2058                // add handling of prenegotiation, change ports if required etc.
2059                //if prenegotiation...
2060        }
2061       
2062     /**
2063     *  @desc modify session and media attributes direction
2064     *           
2065     */
2066     function f_SIP_modSessionDirection(template SDP_attribute p_direction) runs on SipComponent
2067     {
2068      var boolean v_set_direction;
2069      var integer v_mn:= 0, i:=0;
2070      var SDP_attribute_list v_mediaAttributes := {};
2071     
2072          if (ispresent(vc_sdp_local.attributes))
2073                { v_mn:= sizeof(vc_sdp_local.attributes);                       
2074       
2075          for (i :=0;  i < v_mn; i := i+1)
2076          {//for every single attribute (that is not omit)   
2077                 if (ischosen(vc_sdp_local.attributes[i].recvonly)
2078                   or ischosen(vc_sdp_local.attributes[i].sendonly)
2079                   or ischosen(vc_sdp_local.attributes[i].inactive)
2080                   or ischosen(vc_sdp_local.attributes[i].sendrecv))
2081                 {
2082                  v_mediaAttributes[i] := valueof(p_direction);
2083                  v_set_direction := true;
2084                 }
2085                 else // simple copy of attribute
2086                 {v_mediaAttributes[i] := vc_sdp_local.attributes[i]}                                   
2087           }
2088           if (not v_set_direction) // if not sent before
2089               { v_mediaAttributes[v_mn] := valueof(p_direction)};
2090           vc_sdp_local.attributes := v_mediaAttributes;       
2091                };   
2092    }
2093 
2094        /**
2095        *  @desc c
2096        *               
2097        */
2098
2099
2100    /*
2101     *
2102     * @desc check (from remote) and set (local) the session/media attribute lines on directions
2103     * @param p_direction_in incoming SDP attribute that need to be checked
2104     * @param p_direction_out SDP attribute that should be included in the SDP answer (to be returned to peer)
2105     * @return
2106     * @verdict
2107     */
2108        function f_SIP_checksetSDPreqDirection(template SDP_attribute p_direction_in, template SDP_attribute p_direction_out) runs on SipComponent
2109        {       var template SDP_attribute v_direction_out := p_direction_out;
2110                // check incoming SDP attribute
2111                if (not (ispresent(vc_request.messageBody) and f_check_attribute(vc_request.messageBody.sdpMessageBody,p_direction_in)))
2112                        {setverdict(fail);};
2113                if (match(omit,p_direction_out))//not isvalue(v_direction_out))//MRO
2114                        {v_direction_out := f_get_attribute_answer(vc_request.messageBody.sdpMessageBody, p_direction_in);}
2115                f_SIP_modMediaDirection(1, v_direction_out); // handling of attribute in media description
2116                f_SIP_modSessionDirection(v_direction_out); // handling of attribute in session         
2117        }
2118
2119        /*
2120                *
2121                * @desc check (from remote) and set (local)the session/media attribute lines on directions
2122                * @param p_direction_in attribute to be check
2123                * @param p_direction_out attrubyte to be
2124                * @return
2125                * @verdict
2126                */     
2127    function f_SIP_checkSDPrespDirection(template SDP_attribute p_direction_in) runs on SipComponent
2128    {           
2129        // check incoming SDP attribute
2130        if (not (ispresent(vc_response.messageBody) and f_check_attribute(vc_response.messageBody.sdpMessageBody,p_direction_in)))
2131                {setverdict(fail);};
2132    }
2133
2134        /**
2135        *  @desc check media/attribute lines from remote
2136        *               
2137        */
2138        function f_SIP_checkMediaDirection(integer p_medianum, template SDP_attribute p_direction) runs on SipComponent
2139        return boolean
2140        {
2141                var integer v_mn, v_cn := 0, i, j;
2142                var boolean v_result := false;
2143                //increase session version
2144                vc_sdp_remote.origin.session_version := int2str(str2int(vc_sdp_remote.origin.session_version)+1);
2145                // if more than one codec, select the firs one
2146                v_mn:= sizeof(vc_sdp_remote.media_list);
2147                if (p_medianum == 0) //specific media requested
2148                {
2149                        p_medianum := 1; // start checking from first media
2150                };
2151                if (p_medianum > 0) //specific media requested
2152                {
2153                        if (p_medianum > v_mn) {return false}
2154                        else {v_mn := p_medianum}
2155                };
2156                for (i :=p_medianum-1;  i < v_mn; i := i+1)
2157                {
2158                        //for every single media
2159                        if (ispresent(vc_sdp_remote.media_list[i].attributes))
2160                        {
2161                                v_cn := sizeof(vc_sdp_remote.media_list[i].attributes);
2162                                log (v_cn);
2163                        };
2164                        if (sizeof(vc_sdp_remote.media_list[i].attributes)>0)
2165                        {
2166                                // select the first one
2167                                log(vc_sdp_remote.media_list[i].attributes);
2168                                for (j :=0; j<sizeof(vc_sdp_remote.media_list[i].attributes); j:=j+1)
2169                                {
2170                                        log(vc_sdp_remote.media_list[i].attributes[j]);
2171                                        if (ischosen(vc_sdp_remote.media_list[i].attributes[j].recvonly)
2172                                                        or ischosen(vc_sdp_remote.media_list[i].attributes[j].sendonly)
2173                                                        or ischosen(vc_sdp_remote.media_list[i].attributes[j].inactive)
2174                                                        or ischosen(vc_sdp_remote.media_list[i].attributes[j].sendrecv))
2175                                        {
2176                                                if (match(vc_sdp_remote.media_list[i].attributes[j],p_direction))
2177                                                { v_result :=  true; }
2178                                                else { return  false; }
2179                                        }
2180
2181                                        //v_result :=  true; // TODO This is a shortcut since direction attributes are not decoded
2182                                }
2183                        }
2184                }
2185                return v_result
2186        }
2187
2188        /**
2189        *  @desc copy media/attribute lines from remote to local SDP variable
2190        *               
2191        */
2192        function f_copy_SDP() runs on SipComponent
2193        {
2194                if (ispresent(vc_sdp_remote.bandwidth))
2195                                {vc_sdp_local.bandwidth := vc_sdp_remote.bandwidth}
2196                        else {vc_sdp_local.bandwidth := {}};
2197                       
2198                if (ispresent(vc_sdp_remote.media_list))
2199                {
2200                //                      // cleaning of media before assignment 
2201                //                      if (ispresent(vc_sdp_local.media_list))
2202                //                      {
2203                //                              for (var integer i:=0; i<sizeof(vc_sdp_local.media_list); i:=i+1)
2204                //                              {                       
2205                //                                      vc_sdp_local.media_list[i] := omit ;                                             
2206                //                              }                       
2207                //                      };             
2208                        vc_sdp_local.media_list := vc_sdp_remote.media_list;
2209                }
2210        }
2211}//end group SDPOperations
2212
2213group AwaitingMessage {
2214
2215        /**
2216         *
2217         * @desc Function waiting for any MSG -request/response
2218         */
2219        function f_awaitingAnyPassOnTimeout() runs on SipComponent
2220        {
2221          tc_wait.start(PX_SIP_TWAIT);
2222          alt
2223          {
2224                [] SIPP.receive //TAU error if expect (*)
2225                  {
2226                        tc_wait.stop;
2227                        vc_boo_response:=true;
2228                        vc_boo_request:=true;
2229                        //setverdict(pass)
2230                  }
2231                [] tc_wait.timeout
2232                  {
2233                        vc_boo_response:=false;
2234                        vc_boo_request:=false;
2235                        //setverdict (pass)
2236                  }
2237          }
2238        } //end f_awaitingResponsePassOnTimeout
2239
2240        /**
2241         *
2242         * @desc Function waiting for no MSG -request/response
2243         */
2244        function f_awaitingNonePassOnTimeout() runs on SipComponent
2245        {
2246          tc_wait.start(PX_SIP_TWAIT);
2247          alt
2248          {
2249                [] SIPP.receive
2250                  {
2251                        tc_wait.stop;
2252                        setverdict(fail);
2253                  }
2254                [] tc_wait.timeout
2255                  {
2256                        setverdict (pass);
2257                  }
2258          }
2259        } //end f_awaitingResponsePassOnTimeout
2260               
2261        /**
2262         *
2263         * @desc function awaits REGISTER
2264         * @param p_register expected REGISTER request
2265         */     
2266        function f_awaitingREGISTER(in template REGISTER_Request p_register) runs on SipComponent
2267        {
2268                var Request v_request;
2269     
2270                tc_resp.start(PX_SIP_TRESP);
2271                alt
2272                {
2273                  [] SIPP.receive(p_register)-> value v_request sender vc_sent_label
2274                        {
2275                          tc_resp.stop;
2276                          f_setHeadersOnReceiptOfREGISTER(v_request);
2277                        }
2278                }               
2279        }
2280       
2281        /**
2282         *
2283         * @desc function awaits SUBSCRIBE
2284         * @param p_register expected SUBSCRIBE request
2285         */     
2286        function f_awaitingSUBSCRIBE(in template SUBSCRIBE_Request p_register) runs on SipComponent
2287        {
2288                var Request     v_request;
2289     
2290                tc_resp.start(PX_SIP_TRESP);
2291                alt
2292                {
2293                  [] SIPP.receive(p_register)-> value v_request sender vc_sent_label
2294                        {
2295                          tc_resp.stop;
2296                          f_setHeadersOnReceiptOfSUBSCRIBE(v_request);
2297                        }
2298                }               
2299        }
2300       
2301        /**
2302         *
2303         * @desc function awaits REGISTER and sends a 200 OK response
2304         * @param p_reply flag used to avoid the 200OK response sending
2305         */     
2306        function f_awaitingREGISTER_sendReply(in template REGISTER_Request p_register, in boolean p_reply) runs on SipComponent
2307        {
2308                var Request     v_request;
2309     
2310                tc_resp.start(PX_SIP_TRESP);
2311                alt
2312                {
2313                  [] SIPP.receive(p_register)-> value v_request sender vc_sent_label
2314                        {
2315                          tc_resp.stop;
2316                          vc_request := v_request;
2317                          f_setHeadersOnReceiptOfREGISTER(v_request);
2318                          //Answer to the Request
2319                          if (p_reply) {f_send200OK();};
2320                        }
2321                }               
2322        }
2323       
2324
2325        /**
2326         *
2327         * @desc Function waiting for a 200 OK response
2328         * @param p_cSeq_s current cSeq expectation
2329         */
2330        function f_awaitingOkResponse(inout CSeq p_cSeq_s) runs on SipComponent
2331        {
2332
2333        tc_ack.start(PX_SIP_TACK);
2334        alt
2335        {
2336                [] SIPP.receive (mw_Response_Base(c_statusLine200, vc_callId, p_cSeq_s)) -> value vc_response
2337                {
2338                        tc_ack.stop;
2339                        f_setHeadersOnReceiptOfResponse(vc_cSeq, vc_response);
2340                        setverdict(pass)
2341                }
2342        }
2343        } //end awaitingOkResponse
2344
2345        /**
2346         *
2347         * @desc Function waiting for a response
2348         * @param p_Response expected response message
2349         */
2350        function f_awaitingResponse(in template Response p_Response) runs on SipComponent
2351        {
2352          tc_ack.start(PX_SIP_TACK);
2353          alt
2354          {
2355                [] SIPP.receive (p_Response) -> value vc_response
2356                  {
2357                        tc_ack.stop;
2358                        f_setHeadersOnReceiptOfResponse(vc_cSeq, vc_response);
2359                        setverdict(pass)
2360                  }
2361          }
2362        } //end f_awaitingResponse
2363       
2364        /**
2365                 *
2366                 * @desc Function waiting for a response
2367                 * @param p_Response expected response message
2368                 */
2369                function f_awaitingResponsePassOnTimeout(in template Response p_Response) runs on SipComponent
2370                {
2371                  tc_ack.start(PX_SIP_TACK);
2372                  alt
2373                  {
2374                        [] SIPP.receive (p_Response) -> value vc_response
2375                          {
2376                                tc_ack.stop;
2377                                f_setHeadersOnReceiptOfResponse(vc_cSeq, vc_response);
2378                                vc_boo_response:=true;
2379                                //setverdict(pass)
2380                          }
2381                        [] tc_ack.timeout
2382                          {
2383                                vc_boo_response:=false;
2384                                //setverdict (pass)
2385                          }
2386                  }
2387                } //end f_awaitingResponsePassOnTimeout
2388       
2389        /**
2390        *  @desc await INFO request
2391        *                reply with 200 OK
2392        */
2393        function f_awaitingINFO_sendReply(in template INFO_Request p_MSG) runs on SipComponent
2394        {
2395                var INFO_Request        v_MSG;
2396     
2397                tc_resp.start(PX_SIP_TRESP);
2398                alt
2399                {
2400                  [] SIPP.receive(p_MSG)-> value v_MSG sender vc_sent_label
2401                        {
2402                          tc_resp.stop;
2403                          f_setHeadersOnReceiptOfRequest(v_MSG);
2404                          //Answer to the INFO
2405                          f_send200OK();
2406                        }
2407                }
2408        } // end of f_awaitingINFO_sendReply
2409       
2410        /**
2411         *
2412         * @desc function awaiting for an incoming INVITE
2413         * @param p_request expected message
2414         */
2415        function f_awaitingINVITE(template INVITE_Request p_request) runs on SipComponent
2416        {
2417          var INVITE_Request v_INVITE_Request;
2418     
2419          tc_wait.start(PX_SIP_TWAIT);
2420          alt
2421          {
2422                []SIPP.receive  (p_request) -> value v_INVITE_Request sender vc_sent_label
2423                  {
2424                        tc_wait.stop;
2425                        vc_ignore_invite := true;
2426                        vc_first_recv:= true; // communication has started
2427                        f_setHeadersOnReceiptOfINVITE(v_INVITE_Request);
2428                        SIPP.send(m_Response_Base(c_statusLine100, vc_callId, vc_cSeq, vc_from, vc_to, vc_via)) to vc_sent_label;
2429                  }
2430          }
2431        } //end f_awaitingINVITE
2432
2433        /**
2434                *
2435                * @desc function awaiting for an incoming INVITE
2436                * @param p_request expected message
2437                */
2438        function f_awaitingINVITE_No100Response(template INVITE_Request p_request) runs on SipComponent
2439        {
2440          var INVITE_Request v_INVITE_Request;
2441     
2442      tc_wait.start(PX_SIP_TWAIT);
2443      alt
2444      {
2445        []SIPP.receive  (p_request) -> value v_INVITE_Request sender vc_sent_label
2446          {
2447                tc_wait.stop;
2448                vc_ignore_invite := true;
2449                vc_first_recv:= true; // communication has started
2450                f_setHeadersOnReceiptOfINVITE(v_INVITE_Request);
2451            //SIPP.send(m_Response_Base(c_statusLine100, vc_callId, vc_cSeq, vc_from, vc_to, vc_via)) to vc_sent_label;
2452          }
2453      }
2454        } //end f_awaitingInviteRequest
2455
2456        /**
2457         *
2458         * @desc function awaiting for an incoming INVITE
2459         * @param p_request expected message
2460         */
2461        function f_awaitingINVITE_PassOnTimeout(template INVITE_Request p_request) runs on SipComponent
2462        {
2463          var INVITE_Request v_INVITE_Request;
2464     
2465          tc_wait.start(PX_SIP_TWAIT);
2466          alt
2467          {
2468                []SIPP.receive  (p_request) -> value v_INVITE_Request sender vc_sent_label
2469                  {
2470                        tc_wait.stop;
2471                        vc_ignore_invite := true;
2472                        vc_first_recv:= true; // communication has started
2473                        vc_boo_request := true;
2474                        f_setHeadersOnReceiptOfINVITE(v_INVITE_Request);
2475                        SIPP.send(m_Response_Base(c_statusLine100, vc_callId, vc_cSeq, vc_from, vc_to, vc_via)) to vc_sent_label;
2476                  }
2477                []tc_wait.timeout
2478                  {
2479                        vc_boo_request := false;
2480                  }
2481          }
2482        } //end f_awaitingInviteRequest
2483
2484        /**
2485         *
2486         * @desc function awaiting ACK request
2487         */
2488        function f_awaitingACK(in template ACK_Request p_ACK) runs on SipComponent
2489        {
2490          var Request v_ACK_Request;
2491          tc_ack.start(PX_SIP_TACK);
2492     
2493          alt
2494          {
2495                [] SIPP.receive(p_ACK) -> value v_ACK_Request
2496                  {
2497                        tc_ack.stop;
2498                  }
2499                // INVITE may be repeated and shall be ignored
2500                []SIPP.receive(mw_INVITE_Request_Base)
2501                  {
2502                        repeat;
2503                  }
2504                // Ignore othe message
2505                [] SIPP.receive
2506                  {
2507                        repeat;
2508                  }
2509          }
2510        } //end f_awaitingAckRequest
2511
2512        /**
2513         *
2514         * @desc function awaiting BYE and sending 200OK response
2515         * @param p_BYE expected BYE
2516         */
2517        function f_awaitingBYE(in template BYE_Request p_BYE) runs on SipComponent
2518        {
2519          var BYE_Request v_BYE_Request;
2520     
2521          tc_resp.start(PX_SIP_TRESP);
2522          alt
2523          {
2524                []SIPP.receive  (p_BYE) -> value v_BYE_Request sender vc_sent_label
2525                  {
2526                        tc_resp.stop;
2527                        vc_ignore_bye:= true;
2528                        f_setHeadersOnReceiptOfBYE(v_BYE_Request);
2529                        //f_send200OK();
2530                  }
2531          }             
2532        } // end f_awaitingBYE
2533
2534        /**
2535         *
2536         * @desc function awaiting BYE and sending 200OK response
2537         * @param p_BYE expected BYE
2538         */
2539        function f_awaitingBYE_sendReply
2540        (in template BYE_Request p_BYE) runs on SipComponent
2541        {
2542          var BYE_Request v_BYE_Request;
2543     
2544          tc_resp.start(PX_SIP_TRESP);
2545          alt
2546          {
2547                []SIPP.receive  (p_BYE) -> value v_BYE_Request sender vc_sent_label
2548                  {
2549                        tc_resp.stop;
2550                        vc_ignore_bye:= true;
2551                        f_setHeadersOnReceiptOfBYE(v_BYE_Request);
2552                        f_send200OK();
2553                  }
2554          }             
2555        } // end f_awaitingBYE_sendReply
2556       
2557        /**
2558         *
2559         * @desc function awaiting BYE and sending 200OK response
2560         * @param p_BYE expected BYE
2561         */
2562        function f_awaitingBYE_sendReply_PassOnTimeout(in template BYE_Request p_BYE) runs on SipComponent
2563        {
2564          var BYE_Request v_BYE_Request;
2565     
2566          tc_resp.start(PX_SIP_TRESP);
2567          alt
2568          {
2569                []SIPP.receive  (p_BYE) -> value v_BYE_Request sender vc_sent_label
2570                  {
2571                        tc_resp.stop;
2572                        vc_ignore_bye:= true;
2573                        vc_boo_request := true;
2574                        f_setHeadersOnReceiptOfBYE(v_BYE_Request);
2575                        f_send200OK();
2576                  }
2577                []tc_resp.timeout
2578                  {
2579                        vc_boo_request := false;
2580                  }
2581               
2582          }             
2583        } // end f_awaitingBYE_sendReply_PassOnTimeout
2584
2585        /**
2586        *
2587        * @desc function awaiting CANCEL
2588        * @param p_CANCEL expected CANCEL
2589        */
2590        function f_awaitingCANCEL(in template CANCEL_Request p_CANCEL) runs on SipComponent
2591        {
2592                var CANCEL_Request v_MSG;
2593     
2594                tc_resp.start(PX_SIP_TRESP);
2595                alt
2596                {
2597                []SIPP.receive  (p_CANCEL) -> value v_MSG sender vc_sent_label
2598                  {
2599                        tc_resp.stop;
2600                        f_setHeadersOnReceiptOfRequest(v_MSG);
2601                  }
2602                }               
2603        } // end f_awaitingCANCEL
2604        /**
2605        *  @desc await MESSAGE request
2606        */
2607        function f_awaitingMESSAGE(in template MESSAGE_Request p_MSG) runs on SipComponent
2608        {
2609                var MESSAGE_Request     v_MSG;
2610 
2611                tc_resp.start(PX_SIP_TRESP);
2612                alt
2613                {
2614                  [] SIPP.receive(p_MSG)-> value v_MSG sender vc_sent_label
2615                        {
2616                          tc_resp.stop;
2617                          f_setHeadersOnReceiptOfRequest(v_MSG);
2618                          //Answer to the MESSAGE
2619                          //f_send200OK();
2620                        }
2621                }
2622        } // end of f_awaitingMESSAGE
2623       
2624        /**
2625        *  @desc await MESSAGE request
2626        *                reply with 200 OK
2627        */
2628        function f_awaitingMESSAGE_sendReply() runs on SipComponent
2629        {
2630                var MESSAGE_Request     v_MSG;
2631     
2632                tc_resp.start(PX_SIP_TRESP);
2633                alt
2634                {
2635                  [] SIPP.receive(mw_MESSAGE_Request_Base(vc_callId))-> value v_MSG sender vc_sent_label
2636                        {
2637                          tc_resp.stop;
2638                          f_setHeadersOnReceiptOfRequest(v_MSG);
2639                          //Answer to the MESSAGE
2640                          f_send200OK();
2641                        }
2642                }               
2643                       
2644        } // end of f_awaitingMESSAGE_sendReply
2645
2646        /**
2647        *  @desc await MESSAGE request
2648        */
2649        function f_awaitingMESSAGE_sendReply_PassOnTimeout(in template MESSAGE_Request p_MSG) runs on SipComponent
2650        {
2651                var MESSAGE_Request     v_MSG;
2652 
2653                tc_resp.start(PX_SIP_TRESP);
2654                alt
2655                {
2656                  [] SIPP.receive(p_MSG)-> value v_MSG sender vc_sent_label
2657                        {
2658                          tc_resp.stop;
2659                          f_setHeadersOnReceiptOfRequest(v_MSG);
2660                          //Answer to the MESSAGE
2661                          //f_send200OK();
2662                          vc_boo_request := true;
2663                          f_send200OK();
2664                          //setverdict (pass);
2665                        }
2666                  [] tc_resp.timeout
2667                        {
2668                          vc_boo_request := false;
2669                          //setverdict (pass);
2670                        }
2671                }
2672        } // end of f_awaitingMESSAGE_PassOnTimeout
2673       
2674        /**
2675        *  @desc await NOTIFY request
2676        *                reply with 200 OK
2677        */
2678        function f_awaitingNOTIFY_sendReply(in template NOTIFY_Request p_MSG) runs on SipComponent
2679        {
2680                var NOTIFY_Request      v_MSG;
2681     
2682                tc_resp.start(PX_SIP_TRESP);
2683                alt
2684                {
2685                  [] SIPP.receive(p_MSG)-> value v_MSG sender vc_sent_label
2686                        {
2687                          tc_resp.stop;
2688                          f_setHeadersOnReceiptOfRequest(v_MSG);
2689                          //Answer to the NOTIFY
2690                          f_send200OK();
2691                        }
2692                }
2693        } // end of f_awaitingNOTIFY_sendReply 
2694
2695    /**
2696    *  @desc await PRACK request
2697    *            reply with 200 OK
2698    */
2699    function f_awaitingPRACK_sendReply(in template PRACK_Request p_MSG) runs on SipComponent
2700    {
2701        var PRACK_Request       v_MSG;
2702     
2703        tc_resp.start(PX_SIP_TRESP);
2704        alt
2705        {
2706                        [] SIPP.receive(p_MSG)-> value v_MSG sender vc_sent_label
2707                {
2708                                tc_resp.stop;
2709                                f_setHeadersOnReceiptOfRequest(v_MSG);
2710                                //Answer to the PRACK
2711                                f_send200OK();
2712                }
2713        }               
2714               
2715    } // end of f_awaitingPRACK_sendReply
2716       
2717                /**
2718        *  @desc await PUBLISH request
2719        *                reply with 200 OK
2720        */
2721        function f_awaitingPUBLISH_sendReply(in template PUBLISH_Request p_MSG) runs on SipComponent
2722        {
2723                var PUBLISH_Request     v_MSG;
2724 
2725                tc_resp.start(PX_SIP_TRESP);
2726                alt
2727                {
2728                  [] SIPP.receive(p_MSG)-> value v_MSG sender vc_sent_label
2729                        {
2730                          tc_resp.stop;
2731                          f_setHeadersOnReceiptOfRequest(v_MSG);
2732                          //Answer to the PUBLISH
2733                          f_send200OK();
2734                        }
2735                }               
2736               
2737        } // end of f_awaitingPUBLISH_sendReply
2738       
2739        /**
2740        *  @desc await UPDATE request
2741        */
2742        function f_awaitingUPDATE(in template UPDATE_Request p_MSG) runs on SipComponent
2743        {
2744                var UPDATE_Request      v_MSG;
2745 
2746                tc_resp.start(PX_SIP_TRESP);
2747                alt
2748                {
2749                                [] SIPP.receive(p_MSG)-> value v_MSG sender vc_sent_label
2750                        {
2751                                        tc_resp.stop;
2752                                        f_setHeadersOnReceiptOfRequest(v_MSG);
2753                        }
2754                }
2755        } // end of f_awaitingUPDATE   
2756       
2757        /**
2758        *  @desc await UPDATE request
2759        *                reply with 200 OK
2760        */
2761        function f_awaitingUPDATE_sendReply(in template UPDATE_Request p_MSG) runs on SipComponent
2762        {
2763                var UPDATE_Request      v_MSG;
2764 
2765                tc_resp.start(PX_SIP_TRESP);
2766                alt
2767                {
2768                        [] SIPP.receive(p_MSG)-> value v_MSG sender vc_sent_label
2769                                {
2770                                        tc_resp.stop;
2771                                        f_setHeadersOnReceiptOfRequest(v_MSG);
2772                                        //Answer to the UPDATE
2773                                        f_send200OK();
2774                                }
2775                }               
2776
2777        } // end of f_awaitingUPDATE_sendReply
2778       
2779               
2780        /**
2781        *  @desc await REFER request
2782        */
2783        function f_awaitingREFER(in template REFER_Request p_MSG) runs on SipComponent
2784        {
2785                var REFER_Request v_MSG;
2786 
2787                tc_resp.start(PX_SIP_TRESP);
2788                alt
2789                {
2790                        [] SIPP.receive(p_MSG)-> value v_MSG sender vc_sent_label
2791                        {
2792                                        tc_resp.stop;
2793                                        f_setHeadersOnReceiptOfRequest(v_MSG);
2794                        }
2795                }
2796        } // end of f_awaitingUPDATE
2797       
2798} // end AwaitingMessage
2799
2800group SendMessage {
2801
2802        /**
2803        *
2804        * @desc  send ACK message, update the route and recordRoute header fields depending on boolean flags
2805        * @param p_request template of the message to be sent
2806        */     
2807        function f_SendACK(template ACK_Request p_request) runs on SipComponent
2808        {
2809                p_request.msgHeader.route               := f_route();           // update the route header field depending on vc_boo_route
2810                // n/a p_request.msgHeader.recordRoute := f_recordroute(); // update the route header field depending on vc_boo_route
2811                SIPP.send(p_request) to vc_sent_label;   
2812        }
2813       
2814        /**
2815        *
2816        * @desc  send BYE message, update the route and recordRoute header fields depending on boolean flags
2817        * @param p_request template of the message to be sent
2818        */     
2819        function f_SendBYE(template BYE_Request p_request) runs on SipComponent
2820        {
2821                f_setHeadersGeneral(vc_cSeq, "BYE"); // cseq, contact, branch, via
2822                p_request.msgHeader.route               := f_route();           // update the route header field depending on vc_boo_route
2823                p_request.msgHeader.recordRoute := f_recordroute(); // update the route header field depending on vc_boo_route
2824                SIPP.send(p_request) to vc_sent_label;   
2825        }
2826       
2827        /**
2828        *
2829        * @desc  send CANCEL message
2830        * @param p_request template of the message to be sent
2831        */     
2832        function f_SendCANCEL(template CANCEL_Request p_request) runs on SipComponent
2833        {
2834                f_setHeadersGeneral(vc_cSeq, "CANCEL"); // cseq, contact, branch, via
2835                SIPP.send(p_request) to vc_sent_label;   
2836        }
2837               
2838        /**
2839        *
2840        * @desc  send INFO message
2841        * @param p_request template of the message to be sent
2842        */     
2843        function f_SendINFO(template INFO_Request p_request) runs on SipComponent
2844        {
2845                f_setHeadersGeneral(vc_cSeq, "INFO"); // cseq, contact, branch, via
2846                SIPP.send(p_request) to vc_sent_label;
2847        }
2848       
2849        /**
2850        *
2851        * @desc  send INVITE message
2852        * @param p_request template of the message to be sent
2853        */     
2854        function f_SendINVITE(template INVITE_Request p_request) runs on SipComponent
2855        {
2856                vc_requestFor407 := valueof(p_request);
2857                SIPP.send(p_request) to vc_sent_label;
2858                if(PX_SIP_INVITE_AUTHENTICATION_ENABLED) {a_altstep_401or407();};         
2859        }
2860
2861        /**
2862        *
2863        * @desc  send PRACK message
2864        * @param p_request template of the message to be sent
2865        */
2866        function f_SendPRACK(template PRACK_Request p_request) runs on SipComponent
2867        {
2868                f_setHeadersGeneral(vc_cSeq, "PRACK"); // cseq, contact, branch, via   
2869                vc_rAck := valueof(m_RAck(vc_response.msgHeader.rSeq.responseNum, vc_cSeq.seqNumber, vc_cSeq.method));
2870                SIPP.send(p_request) to vc_sent_label;   
2871        }
2872
2873        /**
2874        *
2875        * @desc  send PUBLISH message
2876        * @param p_request template of the message to be sent
2877        */
2878        function f_SendPUBLISH(template PUBLISH_Request p_request) runs on SipComponent
2879        {
2880                SIPP.send(p_request) to vc_sent_label;   
2881        }
2882       
2883        /**
2884        *
2885        * @desc  send REGISTER message
2886        * @param p_request template of the message to be sent
2887        */
2888        function f_SendREGISTER(template REGISTER_Request p_request) runs on SipComponent
2889        {
2890                SIPP.send(p_request) to vc_sent_label;   
2891        }
2892               
2893        /**
2894        *
2895        * @desc  send SUBSCRIBE message
2896        * @param p_request template of the message to be sent
2897        */
2898        function f_SendSUBSCRIBE(template SUBSCRIBE_Request p_request) runs on SipComponent
2899        {
2900                SIPP.send(p_request) to vc_sent_label;   
2901        }
2902               
2903        /**
2904        *
2905        * @desc  send UPDATE message
2906        * @param p_request template of the message to be sent
2907        */
2908        function f_SendUPDATE(template UPDATE_Request p_request) runs on SipComponent
2909        {
2910                f_setHeadersGeneral(vc_cSeq, "UPDATE"); // cseq, contact, branch, via   
2911                vc_requestFor407 := valueof(p_request);
2912                SIPP.send(p_request) to vc_sent_label;   
2913                if(PX_SIP_INVITE_AUTHENTICATION_ENABLED) {a_altstep_401or407();};         
2914        }       
2915       
2916        /**
2917         *
2918         * @desc function send MESSAGE message
2919         * @param p_request template of the message to be sent
2920         */
2921        function f_SendMESSAGE(template MESSAGE_Request p_request) runs on SipComponent
2922        {
2923                SIPP.send(p_request) to vc_sent_label;   
2924        }
2925       
2926        /**
2927         *
2928         * @desc function send NOTIFY message
2929         * @param p_request template of the notify to be sent
2930         */
2931        function f_SendNOTIFY(template NOTIFY_Request p_request) runs on SipComponent
2932        {
2933                SIPP.send(p_request) to vc_sent_label;   
2934        }
2935                       
2936        /**
2937        *
2938        * @desc  send REFER message
2939        * @param p_request template of the message to be sent
2940        */     
2941        function f_SendREFER(template REFER_Request p_request) runs on SipComponent
2942        {
2943                SIPP.send(p_request) to vc_sent_label;
2944        }
2945               
2946        /**
2947        *
2948        * @desc  send 200 OK
2949        */
2950        function f_send200OK() runs on SipComponent
2951        {
2952                f_sendResponse(m_Response_Base(c_statusLine200, vc_callId, vc_cSeq, vc_caller_From, vc_caller_To, vc_via));
2953        }
2954       
2955        /**
2956        *
2957        * @desc  send response
2958        * @param p_request template of the message to be sent
2959        */
2960        function f_sendResponse(template Response p_response) runs on SipComponent
2961        {
2962                p_response.msgHeader.route               := f_route();          // update the route header field depending on vc_boo_route
2963                p_response.msgHeader.recordRoute := f_recordroute(); // update the route header field depending on vc_boo_route
2964                SIPP.send(p_response) to vc_sent_label;
2965        }
2966
2967} // end SendMessage
2968
2969group GlobalSteps {
2970        /**
2971         *
2972         * @desc component initialization
2973         * @param p_cSeq_s cSeq value to be assigned to the component variable
2974         */
2975        function f_init_component(inout CSeq p_cSeq_s)  runs on SipComponent
2976        {
2977                //Variables
2978                vc_cSeq := p_cSeq_s;
2979       
2980                //Defaults
2981                vc_def_catchSyncStop := activate(a_Sip_catchSyncStop());
2982                vc_default := activate (a_clearRegistration());
2983        }
2984       
2985        /**
2986         *
2987         * @desc component termination
2988         */
2989        function f_terminate_component() runs on SipComponent
2990        {
2991                deactivate;
2992                stop;
2993        }
2994
2995        /**
2996         *
2997         * @desc setting of user parameters with PIXIT values
2998         * @param p_user identifies the selected user configuration and location
2999         */
3000        function f_init_userprofile(in integer p_user) runs on SipComponent
3001        {
3002                vc_userprofile.id := p_user;
3003               
3004                select(p_user){
3005                        case (c_userProfile_SIP1_home) { //variant c_userProfile_SIP1_home
3006                        vc_userprofile.currPort := PX_SIP_TS1_PORT;
3007                        vc_userprofile.currIpaddr := PX_SIP_TS1_IPADDR;
3008                        vc_userprofile.contactPort := PX_SIP_TS1_PORT;
3009                        vc_userprofile.contactIpaddr := PX_SIP_TS1_IPADDR;
3010                        vc_userprofile.bearerIpaddr := PX_SIP_TS1_BEARER_IPADDR;
3011                        vc_userprofile.homeDomain := PX_SIP_TS1_LOCAL_DOMAIN;   
3012                        vc_userprofile.publUsername := PX_SIP_TS1_LOCAL_USER;
3013                        vc_userprofile.qop := PX_SIP_SUT_UE1_QOP;
3014                        vc_userprofile.privUsername := PX_SIP_SUT_UE1_USERNAME;
3015                        vc_userprofile.passwd := PX_SIP_SUT_UE1_PASSWD;
3016                        vc_userprofile.registrarDomain := PX_SIP_SUT_REGISTRAR_DOMAIN;
3017                        }
3018                        case (c_userProfile_SIP2_home) { //variant c_userProfile_SIP2_home
3019                        vc_userprofile.currPort := PX_SIP_TS2_PORT;
3020                        vc_userprofile.currIpaddr := PX_SIP_TS2_IPADDR;
3021                        vc_userprofile.contactPort := PX_SIP_TS2_PORT;
3022                        vc_userprofile.contactIpaddr := PX_SIP_TS2_IPADDR;
3023                        vc_userprofile.bearerIpaddr := PX_SIP_TS2_BEARER_IPADDR;       
3024                        vc_userprofile.homeDomain := PX_SIP_TS2_LOCAL_DOMAIN;   
3025                        vc_userprofile.publUsername := PX_SIP_TS2_LOCAL_USER;
3026                        vc_userprofile.qop := PX_SIP_SUT_UE2_QOP;
3027                        vc_userprofile.privUsername := PX_SIP_SUT_UE2_USERNAME;
3028                        vc_userprofile.passwd := PX_SIP_SUT_UE2_PASSWD;
3029                        vc_userprofile.registrarDomain := PX_SIP_SUT_REGISTRAR_DOMAIN;
3030                        }
3031               
3032                }
3033        }
3034
3035        /**
3036         *
3037         * @desc function waits for particular time that allows the SUT to return to idle state
3038         */     
3039        function f_awaitSUTidle() runs on SipComponent
3040        {
3041                vc_ignore4xx := true; // allow 4xx in default
3042                tc_noAct.start;
3043                alt {
3044                        [] tc_noAct.timeout{}           
3045                        }
3046        }       
3047       
3048     /**
3049      *
3050      * @desc function waits for particular time before next expected message
3051      */       
3052      function f_wait(float p_time) runs on SipComponent
3053     {
3054      tc_noAct.start(p_time);
3055      alt {
3056       [] tc_noAct.timeout{}           
3057       }
3058     } 
3059 
3060        /**
3061         *
3062         * @desc function cause termination of a PTC
3063         * @param p_syncPoint dummy parameter (copied from the common lib)
3064         */     
3065        function f_check2Null(in charstring p_syncPoint) runs on SipComponent
3066        {
3067                        //!= pass does not work, because in case of "none" execution shall continue
3068                        if (getverdict == inconc or getverdict == fail){
3069                                log("**** f_check2Null: Verdict evaluated to fail or inconc. Stopping test execution now ");
3070                                f_selfOrClientSyncAndVerdict (p_syncPoint, e_error) ;
3071                        }//end if
3072        }
3073       
3074/*
3075 *
3076 * @desc original copied from older LibCommon_VerdictControl
3077 */
3078        function f_getVerdict()
3079        return FncRetCode {
3080                var FncRetCode v_ret := e_error;
3081                if (getverdict == pass or getverdict == none) {
3082                        v_ret := e_success;     
3083                }
3084                return v_ret;
3085        }
3086       
3087}// end group GlobalSteps
3088
3089group Registration {
3090       
3091        /**
3092         *
3093         * @desc  registration and authentication with MD5
3094         * @param p_cSeq_s              cseq parameter
3095         * @param p_register    register template
3096         * @param p_auth                flag indicating if authentication is needed
3097         */
3098        function f_Registration(inout CSeq p_cSeq_s, template REGISTER_Request p_register, in boolean p_auth) runs on SipComponent
3099        {
3100          var REGISTER_Request v_request := valueof(p_register);
3101         
3102          if (PX_SIP_REGISTRATION)
3103          {
3104                f_setHeaders_REGISTER(p_cSeq_s);
3105                f_SendREGISTER(v_request); //LibSip
3106               
3107                //awaiting of 401 and sending 2nd REGISTER and awaiting 200 OK REGISTER
3108                if (p_auth)
3109                {
3110                  // receiving 401 Unauthorized response.
3111                  // and Re-send REGISTER request with Authorization header
3112                  tc_ack.start(PX_SIP_TACK);
3113                  alt
3114                  {
3115                        [] SIPP.receive (mw_Response_Base(c_statusLine401, vc_callId, p_cSeq_s)) -> value vc_response
3116                          {
3117                                tc_ack.stop;
3118                                // set headers via, cseq and authorization
3119                                f_setHeaders_2ndREGISTER();
3120                                // Re-send protected REGISTER
3121                                f_SendREGISTER(v_request);//LibSip
3122                   
3123                    // awaiting 200 OK REGISTER
3124                                f_awaitingOkResponse(p_cSeq_s);
3125                                f_getServiceRouteMapIntoRouteInRegistration(p_cSeq_s, vc_response);
3126                          }
3127                        [] SIPP.receive (mw_Response_Base(c_statusLine200, vc_callId, p_cSeq_s))
3128                          {
3129                                tc_ack.stop;
3130                                log ("Authorization was not requested as expected");
3131                                setverdict(inconc)
3132                          }
3133                  }
3134                }
3135                else
3136                {
3137                  f_awaitingOkResponse(p_cSeq_s);
3138                  f_getServiceRouteMapIntoRouteInRegistration(p_cSeq_s, vc_response);
3139                }     
3140
3141          };
3142        }//end function f_Registration
3143
3144
3145        /**
3146         *
3147         * @desc remove registration
3148         * @param p_cSeq_s cseq parameter
3149         */     
3150        function f_RemoveRegistration(inout CSeq p_cSeq) runs on SipComponent
3151        {
3152          var CommaParam_List v_challenge;
3153          var Credentials v_credentials;
3154          var REGISTER_Request v_request := valueof(m_REGISTER_Request_expires(vc_requestUri, vc_callId,
3155          p_cSeq,  vc_from, vc_to, vc_via, vc_contact, vc_authorization, "0"));
3156         
3157          if (PX_SIP_REGISTRATION)
3158          {
3159                f_setHeaders_deREGISTER(p_cSeq);
3160     
3161                f_SendREGISTER(v_request);
3162                if (PX_SIP_REGISTER_AUTHENTICATION_ENABLED)
3163                {
3164                        // receiving 401 Unauthorized response.
3165                        // and Re-send REGISTER request with Authorization header
3166                        tc_ack.start(PX_SIP_TACK);
3167                        alt
3168                        {
3169                          [] SIPP.receive       (mw_Response_Base(c_statusLine401, vc_callId, p_cSeq)) -> value vc_response
3170                                {
3171                                  tc_ack.stop;
3172                                  // set headers via, cseq and authorization
3173                                  f_setHeaders_2ndREGISTER();
3174                                  // Re-send protected REGISTER
3175                                  f_SendREGISTER(v_request);//LibSip
3176                                 
3177                                  // awaiting 200 OK REGISTER
3178                                  f_awaitingOkResponse(p_cSeq);
3179                                  f_getServiceRouteMapIntoRouteInRegistration(p_cSeq, vc_response);
3180                                }
3181                          [] SIPP.receive       (mw_Response_Base(c_statusLine200, vc_callId, p_cSeq))
3182                                {
3183                                  tc_ack.stop;
3184                                  log ("Authorization was not requested as expected");
3185                                  setverdict(inconc)
3186                                }
3187                        }
3188                }
3189                else
3190                {
3191                  f_awaitingOkResponse(p_cSeq);
3192                }
3193          }
3194        } // end f_RemoveRegistration
3195
3196        /**
3197         *
3198         * @desc remove registration without authorization
3199         * @param p_cSeq_s cseq parameter
3200         */     
3201        function f_RemoveRegistration_wo_authorization(inout CSeq p_cSeq) runs on SipComponent
3202        {
3203          var SemicolonParam_List tmp_params;
3204          if (PX_SIP_REGISTRATION)
3205          {
3206                f_setHeaders_deREGISTER(p_cSeq);
3207        f_SendREGISTER(m_REGISTER_Request_expires(vc_requestUri, vc_callIdReg, p_cSeq,
3208                  vc_from, vc_to, vc_via, vc_contact, vc_authorization, "0" ));
3209            f_awaitingOkResponse(p_cSeq);               
3210          }
3211        } // end f_RemoveRegistration_wo_authorization
3212
3213}//end group Registration
3214
3215        group Subscription {
3216       
3217                /**
3218                 *
3219                 * @desc  UE send subscrbe, await on 200 OK, await notify and send 200 OK
3220                 * @param p_cSeq_s              cseq parameter
3221                 * @param p_register    subscribe template
3222                 */
3223                function f_Subscription(inout CSeq p_cSeq_s, template SUBSCRIBE_Request p_subscribe) runs on SipComponent
3224                {
3225                  f_setHeaders_SUBSCRIBE(p_cSeq_s);
3226                  //send SUBSCRIBE
3227                  f_SendSUBSCRIBE(p_subscribe);
3228                  // awaiting 200 OK SUBSCRIBE
3229                  f_awaitingOkResponse(p_cSeq_s);
3230                 
3231                  //await NOTIFY and send reply 200 OK
3232                  f_awaitingNOTIFY_sendReply(mw_NOTIFY_Request_Base(vc_callId));
3233         
3234                }//end function f_Subscription
3235
3236                /**
3237                 *
3238                 * @desc  UE send subscrbe, await on 200 OK, await notify and send 200 OK
3239                 * @param p_cSeq_s              cseq parameter
3240                 * @param p_register    subscribe template
3241                 */
3242                function f_SubscriptionWithNotification(inout CSeq p_cSeq_s, template SUBSCRIBE_Request p_subscribe, template NOTIFY_Request p_notify) runs on SipComponent
3243                {
3244                  f_setHeaders_SUBSCRIBE(p_cSeq_s);
3245                  //send SUBSCRIBE
3246                  f_SendSUBSCRIBE(p_subscribe);
3247                  // awaiting 200 OK SUBSCRIBE
3248                  f_awaitingOkResponse(p_cSeq_s);
3249                 
3250                  //await NOTIFY and send reply 200 OK
3251                  f_awaitingNOTIFY_sendReply(p_notify);
3252         
3253                }//end function f_Subscription
3254
3255        }//end group Subscription
3256
3257group Preambles {
3258       
3259        /**
3260         *
3261         * @desc  Set variables and default initialization for user profile
3262         * @param p_userprofile user profile of call
3263         * @param p_cSeq_s              cseq parameter
3264         */
3265        function f_SIP_preamble_woREG(in integer p_userprofile, inout CSeq p_cSeq_s)  runs on SipComponent
3266        {
3267                //varables and altsteps
3268                f_init_component(p_cSeq_s);
3269
3270                //Preamble
3271                f_init_userprofile(p_userprofile); // assignment of PIXIT values to component variable
3272                vc_sdp_local := valueof(m_SDP_bandwidth(valueof(m_media_dynPT(PX_SIP_SDP_dyn, PX_SIP_SDP_encoding)), vc_userprofile));
3273        }
3274       
3275        /**
3276         *
3277         * @desc  Set variables and default initialization for user profile and handle registration and authentication with MD5
3278         * @param p_userprofile         user profile of call
3279         * @param p_cSeq_s                      cseq parameter
3280         * @param p_register            register template
3281         */
3282        function f_SIP_preamble_withREG(in integer p_userprofile, inout CSeq p_cSeq_s, template REGISTER_Request p_register)  runs on SipComponent
3283        {
3284                //preamble
3285                f_SIP_preamble_woREG(p_userprofile, p_cSeq_s);
3286               
3287                //Registration, Awaiting
3288                f_Registration(p_cSeq_s, p_register, PX_SIP_REGISTER_AUTHENTICATION_ENABLED);
3289        }       
3290       
3291}// end group Preambles
3292
3293group Postambles {
3294
3295        /**
3296         *
3297         * @desc function send BYE and awaits reponse
3298         * @param p_CallId parameter for outgoing BYE
3299         * @param p_cSeq parameter for outgoing BYE
3300         * @param p_from parameter for outgoing BYE
3301         * @param p_to parameter for outgoing BYE
3302         * @param p_reqHostPort parameter for outgoing BYE
3303         */
3304        function f_terminateCall(SipUrl p_requestUri, CallId p_CallId, inout CSeq p_cSeq, From p_from,
3305          template To p_to) runs on SipComponent
3306        {
3307          // Sending of a BYE request to release the call and expect a final response
3308          f_SendBYE(m_BYE_Request_cause(p_requestUri, p_CallId, p_cSeq, p_from, valueof(p_to), vc_via, PX_SIP_BYE_CAUSE));
3309     
3310          tc_resp.start(PX_SIP_TRESP);
3311          alt
3312          {
3313                [] SIPP.receive (mw_Response_Base(mw_statusLine1xx, p_CallId, p_cSeq))
3314                  {
3315                        repeat;
3316                  }
3317                [] SIPP.receive (mw_Response_Base(mw_statusLineFinal, p_CallId, p_cSeq))
3318                  {
3319                        tc_resp.stop;
3320                  }
3321                [] tc_resp.timeout
3322                  {
3323                        stop
3324                  }
3325          }
3326        } // end function f_terminateCall
3327
3328        function f_cancelCall(template CANCEL_Request p_request)
3329        runs on SipComponent
3330        {
3331          // This function is called to bring back the IUT in idle condition
3332          // in case of errors or unexpected behaviour.
3333     
3334          // Sending of a CANCEL request with the same Cseq
3335          f_SendCANCEL(p_request);
3336          tc_resp.start(PX_SIP_TRESP);
3337          alt
3338          {
3339                [] SIPP.receive (mw_Response_Base(c_statusLine200, vc_callId, vc_cSeq))
3340                  {
3341                        tc_resp.stop;
3342                  }
3343          }
3344        }
3345
3346} // end group Postambles
3347
3348group SipChecks
3349{
3350
3351
3352        /*
3353        *  @desc check the presence of conversation at SIP side
3354        *               
3355        */
3356        function f_check_Conversation() runs on SipComponent
3357        {
3358        var boolean v_result;
3359        var charstring v_question := "confirm if conversation at SIP port";
3360               
3361        if (PX_SIP_CheckConversation) {                         
3362                opPort.call(s_SIP_conversation:{v_question, -})
3363                {[] opPort.getreply(s_SIP_conversation:{-, true}) {}
3364                 [] opPort.getreply(s_SIP_conversation:{-, false})
3365                        {all timer.stop;
3366                         setverdict(fail);
3367                         syncPort.send(m_syncClientStop);
3368                         stop;}
3369                }
3370        }
3371
3372        f_selfOrClientSyncAndVerdict(c_uPlane, f_getVerdict()); // Note: implemented in test bodies
3373               
3374        return                 
3375        } // end of f_check_Conversation
3376
3377        /*
3378        *  @desc check the presence of conversation at SIP side
3379        *               
3380        */
3381        function f_check_Ringing() runs on SipComponent
3382        {
3383        var boolean v_result;
3384        var charstring v_question := "confirm if ringing at SIP port";
3385               
3386        if (PX_SIP_CheckRinging) {                             
3387                opPort.call(s_SIP_ringing:{v_question, -})
3388                {[] opPort.getreply(s_SIP_ringing:{-, true}) {}
3389                 [] opPort.getreply(s_SIP_ringing:{-, false})
3390                        {all timer.stop;
3391                         setverdict(fail);
3392                         syncPort.send(m_syncClientStop);
3393                         stop;}
3394                }
3395        }
3396
3397        f_selfOrClientSyncAndVerdict(c_Ringing, f_getVerdict());
3398        return                 
3399        } // end of f_check_Ringing
3400
3401        /*
3402        *  @desc check the announcement at SIP side (UE A)
3403        *               
3404        */
3405        function f_check_AnnouncementUE_A() runs on SipComponent
3406        {
3407        var boolean v_result;
3408        var charstring v_question := "confirm if announcement at UE A";
3409               
3410        if (PX_SIP_CheckConversation) {                         
3411                opPort.call(s_SIP_announcementA:{v_question, -})
3412                {[] opPort.getreply(s_SIP_announcementA:{-, true}) {}
3413                 [] opPort.getreply(s_SIP_announcementA:{-, false})
3414                        {all timer.stop;
3415                         setverdict(fail);
3416                         syncPort.send(m_syncClientStop);
3417                         stop;}
3418                }
3419        }
3420
3421        f_selfOrClientSyncAndVerdict(c_annoucA, f_getVerdict());
3422        return                 
3423        } // end of f_check_AnnouncementUE_A
3424
3425        /*
3426        *  @desc check the announcement at SIP side (UE B)
3427        *               
3428        */
3429        function f_check_AnnouncementUE_B() runs on SipComponent
3430        {
3431        var boolean v_result;
3432        var charstring v_question := "confirm if announcement at UE B";
3433               
3434        if (PX_SIP_CheckConversation) {                         
3435                opPort.call(s_SIP_announcementB:{v_question, -})
3436                {[] opPort.getreply(s_SIP_announcementB:{-, true}) {}
3437                        [] opPort.getreply(s_SIP_announcementB:{-, false})
3438                        {all timer.stop;
3439                                setverdict(fail);
3440                                syncPort.send(m_syncClientStop);
3441                                stop;}
3442                }
3443        }
3444
3445        f_selfOrClientSyncAndVerdict(c_annoucB, f_getVerdict());
3446        return                 
3447        } // end of f_check_AnnouncementUE_B
3448
3449        /*
3450        *  @desc check the announcement at SIP side
3451        *               
3452        */
3453        function f_check_Announcement() runs on SipComponent
3454        {
3455        var boolean v_result;
3456        var charstring v_question := "confirm if announcement at SIP side";
3457               
3458        if (PX_SIP_CheckConversation) {                         
3459                opPort.call(s_SIP_announcement:{v_question, -})
3460                {[] opPort.getreply(s_SIP_announcement:{-, true}) {}
3461                 [] opPort.getreply(s_SIP_announcement:{-, false})
3462                        {all timer.stop;
3463                         setverdict(fail);
3464                         syncPort.send(m_syncClientStop);
3465                         stop;}
3466                }
3467        }
3468
3469        f_selfOrClientSyncAndVerdict(c_annouc, f_getVerdict());
3470        return                 
3471        } // end of f_check_Announcement
3472
3473        /*
3474        *  @desc check the Voice message at SIP side
3475        *               
3476        */
3477        function f_check_VoiceMessage() runs on SipComponent
3478        {
3479        var boolean v_result;
3480        var charstring v_question := "confirm if voice message at SIP side";
3481               
3482        if (PX_SIP_CheckConversation) {                         
3483                opPort.call(s_SIP_voiceMessage:{v_question, -})
3484                {[] opPort.getreply(s_SIP_voiceMessage:{-, true}) {}
3485                 [] opPort.getreply(s_SIP_voiceMessage:{-, false})
3486                        {all timer.stop;
3487                         setverdict(fail);
3488                         syncPort.send(m_syncClientStop);
3489                         stop;}
3490                }
3491        }
3492
3493        f_selfOrClientSyncAndVerdict(c_voicem, f_getVerdict());
3494        return                 
3495        } // end of f_check_Announcement
3496       
3497        /*
3498        *  @desc check the stop of media stream
3499        *               
3500        */
3501        function f_check_MediaStopped() runs on SipComponent
3502        {
3503        var boolean v_result;
3504        var charstring v_question := "confirm if media stream stopped";
3505               
3506        if (PX_SIP_CheckConversation) {                         
3507                opPort.call(s_SIP_mediastopped:{v_question, -})
3508                {[] opPort.getreply(s_SIP_mediastopped:{-, true}) {}
3509                 [] opPort.getreply(s_SIP_mediastopped:{-, false})
3510                        {all timer.stop;
3511                         setverdict(fail);
3512                         syncPort.send(m_syncClientStop);
3513                         stop;}
3514                }
3515        }
3516
3517        f_selfOrClientSyncAndVerdict(c_uPlaneStop, f_getVerdict());
3518        return                 
3519        } // end of f_check_MediaStopped
3520
3521}
3522
3523group DefaultsTestStep
3524{
3525       
3526       
3527        /**
3528        * @desc This default handles receiving of the sync server
3529        *               STOP message and calls the RT HUT postamble. (copy from common lib)
3530        */     
3531        altstep a_Sip_catchSyncStop() runs on SipComponent
3532        {
3533                []      syncPort.receive(m_syncServerStop)
3534                {
3535                        tc_sync.stop ;
3536                        log("**** a_Sip_catchSyncStop: Test component received STOP signal from MTC - going to IDLE state **** ");
3537                        //TODO complete postamble
3538                        f_terminate_component();
3539                        log("**** a_Sip_catchSyncStop: TEST COMPONENT NOW STOPPING ITSELF! **** ") ;
3540                        setverdict(inconc);
3541                        stop ;
3542                }
3543        }
3544       
3545
3546        /**
3547         *
3548         * @desc main default altstep to handle unexpected messages and timeout
3549         * @verdict fail for all unexpected branches
3550         */     
3551        altstep a_clearRegistration() runs on SipComponent
3552        {
3553                var Response v_response;
3554                var Request v_request;
3555                 
3556                [] any timer.timeout
3557                {
3558                        setverdict(fail);
3559                        all timer.stop;
3560                        //TODO check how to solve release of call
3561                        //f_SendCANCEL(m_CANCEL_Request(vc_callId, vc_cSeq, vc_from, vc_cancel_To, vc_reqHostPort, vc_via )); // difference between registration state or transaction state
3562                        f_RemoveRegistration(vc_cSeq);
3563                        f_check2Null("");       
3564                }
3565
3566                // allow repeated INVITEs
3567                [vc_ignore_invite] SIPP.receive(mw_INVITE_Request_Base)
3568                {
3569                  repeat
3570                }
3571
3572                // allow repeated BYEs after ack of the first BYE
3573                [vc_ignore_bye] SIPP.receive (mw_BYE_Request_Base(?))
3574                {
3575                  repeat
3576                }
3577
3578                // allow 100 replies
3579                [] SIPP.receive(mw_Response_Base(c_statusLine100,vc_callId, vc_cSeq))
3580                  {
3581                        repeat
3582                  }
3583                         
3584                //      ignore 181 if flag is set (following TS 183004 §4.5.2.1)                 
3585                [vc_ignore181] SIPP.receive(mw_Response_Base(c_statusLine181,vc_callId, vc_cSeq))-> value v_response sender vc_sent_label
3586                  {
3587                        f_setHeadersOnReceiptOfResponse(v_response.msgHeader.cSeq, v_response);
3588                        repeat;
3589                  }
3590         
3591                // according to SIP chap.8.1.3.2
3592                [] SIPP.receive(mw_Response_Base(c_statusLine183,vc_callId, vc_cSeq))
3593                  {
3594                        repeat;
3595                  }
3596
3597                // ignore 484 if flag is set
3598                [vc_ignore484] SIPP.receive(mw_Response_Base(c_statusLine484,vc_callId, vc_cSeq))
3599                        {
3600                          repeat
3601                        }
3602               
3603                [vc_ignore4xx] SIPP.receive(mw_Response_Base(mw_statusLine4xx,vc_callId, ?))-> value v_response sender vc_sent_label
3604                  {
3605                        f_setHeadersOnReceiptOfResponse(v_response.msgHeader.cSeq, v_response);
3606                        f_SendACK(m_ACK_Request_route(vc_requestUri, vc_callId, v_response.msgHeader.cSeq, vc_from, vc_to, vc_via, vc_route));
3607                        repeat
3608                  }                     
3609               
3610                [vc_ignore200OKinv] SIPP.receive(mw_Response_Base(c_statusLine200, vc_callId, ?))
3611                  {
3612                        repeat
3613                  }
3614       
3615                [] SIPP.receive(mw_INFO_Request_Base(vc_callId))->value v_request sender vc_sent_label
3616                  {
3617                        f_setHeadersOnReceiptOfRequest(v_request);
3618                        f_send200OK();
3619                        repeat
3620                  }
3621                 
3622                //awaiting of subscribe on proxy
3623                [] SIPP.receive(mw_SUBSCRIBE_Request_Base)->value v_request sender vc_sent_label
3624                  {
3625                        f_setHeadersOnReceiptOfRequest(v_request);
3626                        f_send200OK();
3627                        f_setHeadersGeneral(vc_cSeq, "NOTIFY"); // cseq, contact, branch, via
3628                        f_SendNOTIFY(m_NOTIFY_Request_Base(vc_requestUri, vc_callId, vc_cSeq, vc_from, vc_to, vc_via));
3629                        f_awaitingOkResponse(vc_cSeq);
3630                        repeat
3631                  }
3632
3633                // unexpected BYE is acknowledged to avoid retransmissions
3634                [] SIPP.receive(mw_BYE_Request_Base(?))-> value v_request sender vc_sent_label
3635                  {
3636                        setverdict(fail);
3637                        f_setHeadersOnReceiptOfRequest(v_request);
3638                        f_send200OK();
3639                        f_RemoveRegistration(vc_cSeq);
3640                        f_check2Null("");       
3641                        }                         
3642                         
3643                // unexpected CANCEL is acknowledged to avoid retransmissions
3644                [] SIPP.receive(mw_CANCEL_Request_Base(?))-> value v_request sender vc_sent_label
3645                  {
3646                        setverdict(fail);
3647                        f_setHeadersOnReceiptOfRequest(v_request);
3648                        //Answer to the CANCEL
3649                        f_send200OK();
3650                        f_RemoveRegistration(vc_cSeq);
3651                        f_check2Null("");       
3652                        }                         
3653          [] SIPP.receive
3654                {
3655                        setverdict(fail);
3656                        all timer.stop;
3657                        f_SendCANCEL(m_CANCEL_Request_Base(vc_requestUri, vc_callId, vc_cSeq, vc_from, vc_cancel_To, vc_via )); // difference between registration state or transaction state
3658                        f_RemoveRegistration(vc_cSeq);
3659                        f_check2Null("");       
3660                }
3661        }
3662       
3663        /**
3664         *
3665         * @desc altstep handle authentication for INVITE message
3666         */     
3667        altstep a_altstep_401or407() runs on SipComponent {
3668                [] any port.check (receive) {
3669                        var CommaParam_List v_challenge;
3670                        var Credentials v_Credentials;
3671                        var Response v_Response;
3672                        var Request v_Request := valueof (vc_requestFor407);
3673                                       
3674                        tc_ack.start (PX_SIP_TACK);
3675                        alt {
3676                                [] SIPP.receive (mw_Response_Base((c_statusLine401,c_statusLine407),
3677                                                                                          vc_callId,
3678                                                                                          vc_cSeq)) -> value v_Response {
3679                                        tc_ack.stop;
3680                                        //      get tag from To header if available                                                     
3681                                        vc_to := v_Response.msgHeader.toField;
3682                                        if (vc_cSeq.method == "INVITE"){
3683                                                // send ACK
3684                                                f_SendACK(m_ACK_Request_Base(vc_requestUri, vc_callId, vc_cSeq, vc_from, vc_to, vc_via));
3685                                        }                                                       
3686                                        // resent the INVITE message with Proxyauthorization header include
3687                                        // Extract challenge and calculate credentials for a response.
3688                                        if (ischosen (v_Response
3689                                                .msgHeader
3690                                                .proxyAuthenticate
3691                                                .challenge
3692                                                .otherChallenge // instead of digestCln (changed by axr to comply to alcatel)
3693                                                )) {
3694                                                v_challenge :=
3695                                                        v_Response
3696                                                                .msgHeader
3697                                                                .proxyAuthenticate
3698                                                                .challenge
3699                                                                .otherChallenge.authParams;
3700                                                v_Credentials :=
3701                                                        f_calculatecCredentials(vc_userprofile,
3702                                                                vc_requestFor407.msgHeader.cSeq.method,
3703                                                                v_challenge);
3704                                        } else {
3705                                                log ("No scheme in Proxy Authenticate header!!");
3706                                                setverdict (inconc);
3707                                                stop;
3708                                        }
3709
3710                                        vc_branch := c_branchCookie & f_getRndTag();
3711                                        vc_via := {
3712                                                fieldName := VIA_E,
3713                                                viaBody := {
3714                                                        valueof (m_ViaBody_currIpaddr(vc_branch, vc_userprofile))}
3715                                        };
3716
3717                                        v_Request.msgHeader.via := vc_via;
3718                                        // Increment CSeq sequence number of and add the credentials
3719                                        // to the original saved INVITE message.
3720                                        vc_cSeq.method := vc_requestFor407.msgHeader.cSeq.method;
3721                                        vc_cSeq.seqNumber := vc_cSeq.seqNumber + 1;
3722                                        v_Request.msgHeader.cSeq.seqNumber :=
3723                                                vc_cSeq.seqNumber;
3724                                        v_Request.msgHeader.proxyAuthorization.fieldName :=
3725                                                PROXY_AUTHORIZATION_E;
3726                                        v_Request.msgHeader.proxyAuthorization.credentials :=
3727                                                {v_Credentials};
3728                                                       
3729                                        // Re-send the saved INVITE with Authorization header
3730                                        // included.
3731                                        SIPP.send (v_Request) to vc_sent_label;
3732                                }
3733                        }
3734                }
3735        }
3736       
3737       
3738} // end of group DefaultsTestStep
3739} // end module LibSip_Steps
Note: See TracBrowser for help on using the repository browser.