1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 *
16 * Author : Richard GAYRAUD - 04 Nov 2003
17 * Olivier Jacques
18 * From Hewlett Packard Company.
19 * Shriram Natarajan
20 * Peter Higginson
21 * Venkatesh
22 * Lee Ballard
23 * Guillaume TEISSIER from FTR&D
24 * Wolfgang Beck
25 * Marc Van Diest from Belgacom
26 * Charles P. Wright from IBM Research
27 * Michael Stovenour
28 */
29
30 #include <stdlib.h>
31 #include "sipp.hpp"
32 #ifdef HAVE_GSL
33 #include <gsl/gsl_rng.h>
34 #include <gsl/gsl_randist.h>
35 #include <gsl/gsl_cdf.h>
36 #endif
37
38 /************************ Class Constructor *************************/
39
message(int index,const char * desc)40 message::message(int index, const char *desc)
41 {
42 this->index = index;
43 this->desc = desc;
44 pause_distribution = NULL; // delete on exit
45 pause_variable = -1;
46 pause_desc = NULL; // free on exit
47 sessions = 0;
48 bShouldRecordRoutes = 0;
49 bShouldAuthenticate = 0;
50
51 send_scheme = NULL; // delete on exit
52 retrans_delay = 0;
53 timeout = 0;
54
55 recv_response = 0;
56 recv_request = NULL; // free on exit
57 optional = 0;
58 advance_state = true;
59 regexp_match = 0;
60 regexp_compile = NULL; // regfree (if not NULL) and free on exit
61
62 /* Anyway */
63 start_rtd = 0;
64 stop_rtd = 0;
65 repeat_rtd = 0;
66 lost = -1;
67 crlf = 0;
68 hide = 0;
69 display_str = NULL; // free on exit
70 test = -1;
71 condexec = -1;
72 condexec_inverse = false;
73 chance = 0;/* meaning always */
74 next = -1;
75 nextLabel = NULL; // free on exit
76 on_timeout = -1;
77 onTimeoutLabel = NULL; // free on exit
78 timewait = false;
79
80 /* 3pcc extended mode */
81 peer_dest = NULL; // free on exit
82 peer_src = NULL; // free on exit
83
84 /* Statistics */
85 nb_sent = 0;
86 nb_recv = 0;
87 nb_sent_retrans = 0;
88 nb_recv_retrans = 0;
89 nb_timeout = 0;
90 nb_unexp = 0;
91 nb_lost = 0;
92 counter = 0;
93
94 M_actions = NULL; // delete on exit
95
96 M_type = 0;
97
98 M_sendCmdData = NULL; // delete on exit
99 M_nbCmdSent = 0;
100 M_nbCmdRecv = 0;
101
102 content_length_flag = ContentLengthNoPresent;
103
104 /* How to match responses to this message. */
105 start_txn = 0;
106 response_txn = 0;
107 ack_txn = 0;
108 recv_response_for_cseq_method_list = NULL; // free on exit
109 }
110
~message()111 message::~message()
112 {
113 delete(pause_distribution);
114 free(pause_desc);
115 delete(send_scheme);
116 free(recv_request);
117 if (regexp_compile != NULL) {
118 regfree(regexp_compile);
119 }
120 free(regexp_compile);
121
122 free(display_str);
123 free(nextLabel);
124 free(onTimeoutLabel);
125
126 free(peer_dest);
127 free(peer_src);
128
129 delete(M_actions);
130 delete(M_sendCmdData);
131 free(recv_response_for_cseq_method_list);
132 }
133
134 /******** Global variables which compose the scenario file **********/
135
136 scenario *main_scenario;
137 scenario *ooc_scenario;
138 scenario *aa_scenario;
139 scenario *display_scenario;
140
141 /* This mode setting refers to whether we open calls autonomously (MODE_CLIENT)
142 * or in response to requests (MODE_SERVER). */
143 int creationMode = MODE_CLIENT;
144 /* Send mode. Do we send to a fixed address or to the last one we got. */
145 int sendMode = MODE_CLIENT;
146 /* This describes what our 3PCC behavior is. */
147 int thirdPartyMode = MODE_3PCC_NONE;
148
149 /*************** Helper functions for various types *****************/
get_long(const char * ptr,const char * what)150 long get_long(const char *ptr, const char *what)
151 {
152 char *endptr;
153 long ret;
154
155 ret = strtol(ptr, &endptr, 0);
156 if (*endptr) {
157 ERROR("%s, \"%s\" is not a valid integer!\n", what, ptr);
158 }
159 return ret;
160 }
161
get_long_long(const char * ptr,const char * what)162 unsigned long long get_long_long(const char *ptr, const char *what)
163 {
164 char *endptr;
165 unsigned long long ret;
166
167 ret = strtoull(ptr, &endptr, 0);
168 if (*endptr) {
169 ERROR("%s, \"%s\" is not a valid integer!\n", what, ptr);
170 }
171 return ret;
172 }
173
174 /* This function returns a time in milliseconds from a string.
175 * The multiplier is used to convert from the default input type into
176 * milliseconds. For example, for seconds you should use 1000 and for
177 * milliseconds use 1. */
get_time(const char * ptr,const char * what,int multiplier)178 long get_time(const char *ptr, const char *what, int multiplier)
179 {
180 char *endptr;
181 const char *p;
182 long ret;
183 double dret;
184 int i;
185
186 if (!isdigit(*ptr)) {
187 ERROR("%s, \"%s\" is not a valid time!\n", what, ptr);
188 }
189
190 for (i = 0, p = ptr; *p; p++) {
191 if (*p == ':') {
192 i++;
193 }
194 }
195
196 if (i == 1) { /* mm:ss */
197 ERROR("%s, \"%s\" mm:ss not implemented yet!\n", what, ptr);
198 } else if (i == 2) { /* hh:mm:ss */
199 ERROR("%s, \"%s\" hh:mm:ss not implemented yet!\n", what, ptr);
200 } else if (i != 0) {
201 ERROR("%s, \"%s\" is not a valid time!\n", what, ptr);
202 }
203
204 dret = strtod(ptr, &endptr);
205 if (*endptr) {
206 if (!strcmp(endptr, "s")) { /* Seconds */
207 ret = (long)(dret * 1000);
208 } else if (!strcmp(endptr, "ms")) { /* Milliseconds. */
209 ret = (long)dret;
210 } else if (!strcmp(endptr, "m")) { /* Minutes. */
211 ret = (long)(dret * 60000);
212 } else if (!strcmp(endptr, "h")) { /* Hours. */
213 ret = (long)(dret * 60 * 60 * 1000);
214 } else {
215 ERROR("%s, \"%s\" is not a valid time!\n", what, ptr);
216 }
217 } else {
218 ret = (long)(dret * multiplier);
219 }
220 return ret;
221 }
222
get_double(const char * ptr,const char * what)223 double get_double(const char *ptr, const char *what)
224 {
225 char *endptr;
226 double ret;
227
228 ret = strtod(ptr, &endptr);
229 if (*endptr) {
230 ERROR("%s, \"%s\" is not a floating point number!\n", what, ptr);
231 }
232 return ret;
233 }
234
235 #ifdef PCAPPLAY
236 /* Return static buffer to xml value, as with xp_get_value().
237 * If the value is enclosed in [brackets], it is assumed to be
238 * a command-line supplied keyword value (-key). */
xp_get_keyword_value(const char * name)239 static const char* xp_get_keyword_value(const char *name)
240 {
241 const char* ptr = xp_get_value(name);
242 size_t len;
243
244 if (ptr && ptr[0] == '[' && (len = strlen(ptr)) && ptr[len - 1] == ']') {
245 int i = 0;
246 len -= 2; /* without the brackets */
247 while (generic[i]) {
248 const char* keyword = *generic[i];
249 if (strncmp(ptr + 1, keyword, len) == 0 && strlen(keyword) == len) {
250 const char* value = *(generic[i] + 1);
251 return strdup(value);
252 }
253 ++i;
254 }
255 ERROR("%s \"%s\" looks like a keyword value, but keyword not supplied!\n", name, ptr);
256 }
257
258 return ptr;
259 }
260 #endif
261
xp_get_string(const char * name,const char * what)262 static char* xp_get_string(const char *name, const char *what)
263 {
264 char *ptr;
265
266 if (!(ptr = xp_get_value(name))) {
267 ERROR("%s is missing the required '%s' parameter.", what, name);
268 }
269
270 return strdup(ptr);
271 }
272
xp_get_double(const char * name,const char * what)273 static double xp_get_double(const char *name, const char *what)
274 {
275 char *ptr;
276 char *helptext;
277 double val;
278
279 if (!(ptr = xp_get_value(name))) {
280 ERROR("%s is missing the required '%s' parameter.", what, name);
281 }
282 helptext = (char *)malloc(100 + strlen(name) + strlen(what));
283 sprintf(helptext, "%s '%s' parameter", what, name);
284 val = get_double(ptr, helptext);
285 free(helptext);
286
287 return val;
288 }
289
xp_get_long(const char * name,const char * what)290 static long xp_get_long(const char *name, const char *what)
291 {
292 char *ptr;
293 char *helptext;
294 long val;
295
296 if (!(ptr = xp_get_value(name))) {
297 ERROR("%s is missing the required '%s' parameter.", what, name);
298 }
299 helptext = (char *)malloc(100 + strlen(name) + strlen(what));
300 sprintf(helptext, "%s '%s' parameter", what, name);
301 val = get_long(ptr, helptext);
302 free(helptext);
303
304 return val;
305 }
306
xp_get_long(const char * name,const char * what,long defval)307 static long xp_get_long(const char *name, const char *what, long defval)
308 {
309 if (!(xp_get_value(name))) {
310 return defval;
311 }
312 return xp_get_long(name, what);
313 }
314
315
xp_get_bool(const char * name,const char * what)316 static bool xp_get_bool(const char *name, const char *what)
317 {
318 char *ptr;
319 char *helptext;
320 bool val;
321
322 if (!(ptr = xp_get_value(name))) {
323 ERROR("%s is missing the required '%s' parameter.", what, name);
324 }
325 helptext = (char *)malloc(100 + strlen(name) + strlen(what));
326 sprintf(helptext, "%s '%s' parameter", what, name);
327 val = get_bool(ptr, helptext);
328 free(helptext);
329
330 return val;
331 }
332
xp_get_bool(const char * name,const char * what,bool defval)333 static bool xp_get_bool(const char *name, const char *what, bool defval)
334 {
335 if (!(xp_get_value(name))) {
336 return defval;
337 }
338 return xp_get_bool(name, what);
339 }
340
get_txn(const char * txnName,const char * what,bool start,bool isInvite,bool isAck)341 int scenario::get_txn(const char *txnName, const char *what, bool start, bool isInvite, bool isAck)
342 {
343 /* Check the name's validity. */
344 if (txnName[0] == '\0') {
345 ERROR("Variable names may not be empty for %s\n", what);
346 }
347 if (strcspn(txnName, "$,") != strlen(txnName)) {
348 ERROR("Variable names may not contain $ or , for %s\n", what);
349 }
350
351 /* If this transaction has already been used, then we have nothing to do. */
352 str_int_map::iterator txn_it = txnMap.find(txnName);
353 if (txn_it != txnMap.end()) {
354 if (start) {
355 /* We need to fill in the invite field. */
356 transactions[txn_it->second - 1].started++;
357 } else if (isAck) {
358 transactions[txn_it->second - 1].acks++;
359 } else {
360 transactions[txn_it->second - 1].responses++;
361 }
362 return txn_it->second;
363 }
364
365 /* Assign this variable the next slot. */
366 struct txnControlInfo transaction;
367
368 transaction.name = strdup(txnName);
369 if (start) {
370 transaction.started = 1;
371 transaction.responses = 0;
372 transaction.acks = 0;
373 transaction.isInvite = isInvite;
374 } else if (isAck) {
375 /* Does not start or respond to this txn. */
376 transaction.started = 0;
377 transaction.responses = 0;
378 transaction.acks = 1;
379 transaction.isInvite = false;
380 } else {
381 transaction.started = 0;
382 transaction.responses = 1;
383 transaction.acks = 0;
384 transaction.isInvite = false;
385 }
386
387 transactions.push_back(transaction);
388 int txnNum = transactions.size();
389 txnMap[txnName] = txnNum;
390
391 return txnNum;
392 }
393
find_var(const char * varName)394 int scenario::find_var(const char *varName)
395 {
396 return allocVars->find(varName, false);
397 }
398
get_var(const char * varName,const char * what)399 int scenario::get_var(const char *varName, const char *what)
400 {
401 /* Check the name's validity. */
402 if (varName[0] == '\0') {
403 ERROR("Transaction names may not be empty for %s\n", what);
404 }
405 if (strcspn(varName, "$,") != strlen(varName)) {
406 ERROR("Transaction names may not contain $ or , for %s\n", what);
407 }
408
409 return allocVars->find(varName, true);
410 }
411
xp_get_var(const char * name,const char * what)412 int scenario::xp_get_var(const char *name, const char *what)
413 {
414 char *ptr;
415
416 if (!(ptr = xp_get_value(name))) {
417 ERROR("%s is missing the required '%s' variable parameter.", what, name);
418 }
419
420 return get_var(ptr, what);
421 }
422
xp_get_optional(const char * name,const char * what)423 static int xp_get_optional(const char *name, const char *what)
424 {
425 char *ptr = xp_get_value(name);
426
427 if (!ptr) {
428 return OPTIONAL_FALSE;
429 }
430
431 if(!strcmp(ptr, "true")) {
432 return OPTIONAL_TRUE;
433 } else if(!strcmp(ptr, "global")) {
434 return OPTIONAL_GLOBAL;
435 } else if(!strcmp(ptr, "false")) {
436 return OPTIONAL_FALSE;
437 } else {
438 ERROR("Could not understand optional value for %s: %s", what, ptr);
439 }
440
441 return OPTIONAL_FALSE;
442 }
443
444
xp_get_var(const char * name,const char * what,int defval)445 int scenario::xp_get_var(const char *name, const char *what, int defval)
446 {
447 char *ptr;
448
449 if (!(ptr = xp_get_value(name))) {
450 return defval;
451 }
452
453 return xp_get_var(name, what);
454 }
455
get_bool(const char * ptr,const char * what)456 bool get_bool(const char *ptr, const char *what)
457 {
458 char *endptr;
459 long ret;
460
461 if (!strcasecmp(ptr, "true")) {
462 return true;
463 }
464 if (!strcasecmp(ptr, "false")) {
465 return false;
466 }
467
468 ret = strtol(ptr, &endptr, 0);
469 if (*endptr) {
470 ERROR("%s, \"%s\" is not a valid boolean!\n", what, ptr);
471 }
472 return ret ? true : false;
473 }
474
475 /* Pretty print a time. */
time_string(double ms,char * res,int reslen)476 int time_string(double ms, char *res, int reslen)
477 {
478 if (ms < 10000) {
479 /* Less then 10 seconds we represent accurately. */
480 if ((int)(ms + 0.9999) == (int)(ms)) {
481 /* We have an integer, or close enough to it. */
482 return snprintf(res, reslen, "%dms", (int)ms);
483 } else {
484 if (ms < 1000) {
485 return snprintf(res, reslen, "%.2lfms", ms);
486 } else {
487 return snprintf(res, reslen, "%.1lfms", ms);
488 }
489 }
490 } else if (ms < 60000) {
491 /* We round to 100ms for times less than a minute. */
492 return snprintf(res, reslen, "%.1fs", ms/1000);
493 } else if (ms < 60 * 60000) {
494 /* We round to 1s for times more than a minute. */
495 int s = (unsigned int)(ms / 1000);
496 int m = s / 60;
497 s %= 60;
498 return snprintf(res, reslen, "%d:%02d", m, s);
499 } else {
500 int s = (unsigned int)(ms / 1000);
501 int m = s / 60;
502 int h = m / 60;
503 s %= 60;
504 m %= 60;
505 return snprintf(res, reslen, "%d:%02d:%02d", h, m, s);
506 }
507 }
508
509 /* For backwards compatibility, we assign "true" to slot 1, false to 0, and
510 * allow other valid integers. */
get_rtd(const char * ptr,bool start)511 int scenario::get_rtd(const char *ptr, bool start)
512 {
513 if(!strcmp(ptr, (char *)"false"))
514 return 0;
515
516 if(!strcmp(ptr, (char *)"true"))
517 return stats->findRtd("1", start);
518
519 return stats->findRtd(ptr, start);
520 }
521
522 /* Get a counter */
get_counter(const char * ptr,const char * what)523 int scenario::get_counter(const char *ptr, const char *what)
524 {
525 /* Check the name's validity. */
526 if (ptr[0] == '\0') {
527 ERROR("Counter names names may not be empty for %s\n", what);
528 }
529 if (strcspn(ptr, "$,") != strlen(ptr)) {
530 ERROR("Counter names may not contain $ or , for %s\n", what);
531 }
532
533 return stats->findCounter(ptr, true);
534 }
535
536
537 /* Some validation functions. */
538
validate_variable_usage()539 void scenario::validate_variable_usage()
540 {
541 allocVars->validate();
542 }
543
validate_txn_usage()544 void scenario::validate_txn_usage()
545 {
546 for (unsigned int i = 0; i < transactions.size(); i++) {
547 if(transactions[i].started == 0) {
548 ERROR("Transaction %s is never started!\n", transactions[i].name);
549 } else if(transactions[i].responses == 0) {
550 ERROR("Transaction %s has no responses defined!\n", transactions[i].name);
551 }
552 if (transactions[i].isInvite && transactions[i].acks == 0) {
553 ERROR("Transaction %s is an INVITE transaction without an ACK!\n", transactions[i].name);
554 }
555 if (!transactions[i].isInvite && (transactions[i].acks > 0)) {
556 ERROR("Transaction %s is a non-INVITE transaction with an ACK!\n", transactions[i].name);
557 }
558 }
559 }
560
561 /* Apply the next and ontimeout labels according to our map. */
apply_labels(msgvec v,str_int_map labels)562 void scenario::apply_labels(msgvec v, str_int_map labels)
563 {
564 for (unsigned int i = 0; i < v.size(); i++) {
565 if (v[i]->nextLabel) {
566 str_int_map::iterator label_it = labels.find(v[i]->nextLabel);
567 if (label_it == labels.end()) {
568 ERROR("The label '%s' was not defined (index %d, next attribute)\n", v[i]->nextLabel, i);
569 }
570 v[i]->next = label_it->second;
571 }
572 if (v[i]->onTimeoutLabel) {
573 str_int_map::iterator label_it = labels.find(v[i]->onTimeoutLabel);
574 if (label_it == labels.end()) {
575 ERROR("The label '%s' was not defined (index %d, ontimeout attribute)\n", v[i]->onTimeoutLabel, i);
576 }
577 v[i]->on_timeout = label_it->second;
578 }
579 }
580 }
581
get_cr_number(const char * src)582 int get_cr_number(const char *src)
583 {
584 int res=0;
585 while(*src) {
586 if(*src == '\n') res++;
587 src++;
588 }
589 return res;
590 }
591
clean_cdata(char * ptr,int * removed_crlf=NULL)592 static char* clean_cdata(char *ptr, int *removed_crlf = NULL)
593 {
594 char * msg;
595
596 while((*ptr == ' ') || (*ptr == '\t') || (*ptr == '\n')) ptr++;
597
598 msg = (char *) malloc(strlen(ptr) + 3);
599 if(!msg) {
600 ERROR("Memory Overflow");
601 }
602 strcpy(msg, ptr);
603
604 ptr = msg + strlen(msg);
605 ptr --;
606
607 while((ptr >= msg) &&
608 ((*ptr == ' ') ||
609 (*ptr == '\t') ||
610 (*ptr == '\n'))) {
611 if(*ptr == '\n' && removed_crlf) {
612 (*removed_crlf)++;
613 }
614 *ptr-- = 0;
615 }
616
617 if(!strstr(msg, "\n\n")) {
618 strcat(msg, "\n\n");
619 }
620
621 if(ptr == msg) {
622 ERROR("Empty cdata in xml scenario file");
623 }
624 while ((ptr = strstr(msg, "\n "))) {
625 memmove(ptr + 1, ptr + 2, strlen(ptr) - 1);
626 }
627 while ((ptr = strstr(msg, " \n"))) {
628 memmove(ptr, ptr + 1, strlen(ptr));
629 }
630 while ((ptr = strstr(msg, "\n\t"))) {
631 memmove(ptr + 1, ptr + 2, strlen(ptr) - 1);
632 }
633 while ((ptr = strstr(msg, "\t\n"))) {
634 memmove(ptr, ptr + 1, strlen(ptr));
635 }
636
637 return msg;
638 }
639
640
641
642 /********************** Scenario File analyser **********************/
643
checkOptionalRecv(char * elem,unsigned int scenario_file_cursor)644 void scenario::checkOptionalRecv(char *elem, unsigned int scenario_file_cursor)
645 {
646 if (last_recv_optional) {
647 ERROR("<recv> before <%s> sequence without a mandatory message. Please remove one 'optional=true' (element %d).", elem, scenario_file_cursor);
648 }
649 last_recv_optional = false;
650 }
651
scenario(char * filename,int deflt)652 scenario::scenario(char * filename, int deflt)
653 {
654 char * elem;
655 char *method_list = NULL;
656 unsigned int scenario_file_cursor = 0;
657 int L_content_length = 0 ;
658 char * peer;
659 const char* cptr;
660
661 last_recv_optional = false;
662
663 if(filename) {
664 if(!xp_set_xml_buffer_from_file(filename)) {
665 ERROR("Unable to load or parse '%s' xml scenario file", filename);
666 }
667 } else {
668 if(!xp_set_xml_buffer_from_string(default_scenario[deflt])) {
669 ERROR("Unable to load default xml scenario file");
670 }
671 }
672
673 stats = new CStat();
674 allocVars = new AllocVariableTable(userVariables);
675
676 hidedefault = false;
677
678 elem = xp_open_element(0);
679 if (!elem) {
680 ERROR("No element in xml scenario file");
681 }
682 if(strcmp("scenario", elem)) {
683 ERROR("No 'scenario' section in xml scenario file");
684 }
685
686 if ((cptr = xp_get_value("name"))) {
687 name = strdup(cptr);
688 } else {
689 name = strdup("");
690 }
691
692 duration = 0;
693 found_timewait = false;
694
695 scenario_file_cursor = 0;
696
697 while ((elem = xp_open_element(scenario_file_cursor))) {
698 char * ptr;
699 scenario_file_cursor ++;
700
701 if(!strcmp(elem, "CallLengthRepartition")) {
702 ptr = xp_get_string("value", "CallLengthRepartition");
703 stats->setRepartitionCallLength(ptr);
704 free(ptr);
705 } else if(!strcmp(elem, "ResponseTimeRepartition")) {
706 ptr = xp_get_string("value", "ResponseTimeRepartition");
707 stats->setRepartitionResponseTime(ptr);
708 free(ptr);
709 } else if(!strcmp(elem, "Global")) {
710 ptr = xp_get_string("variables", "Global");
711
712 char ** currentTabVarName = NULL;
713 int currentNbVarNames;
714
715 createStringTable(ptr, ¤tTabVarName, ¤tNbVarNames);
716 for (int i = 0; i < currentNbVarNames; i++) {
717 globalVariables->find(currentTabVarName[i], true);
718 }
719 freeStringTable(currentTabVarName, currentNbVarNames);
720 free(ptr);
721 } else if(!strcmp(elem, "User")) {
722 ptr = xp_get_string("variables", "User");
723
724 char ** currentTabVarName = NULL;
725 int currentNbVarNames;
726
727 createStringTable(ptr, ¤tTabVarName, ¤tNbVarNames);
728 for (int i = 0; i < currentNbVarNames; i++) {
729 userVariables->find(currentTabVarName[i], true);
730 }
731 freeStringTable(currentTabVarName, currentNbVarNames);
732 free(ptr);
733 } else if(!strcmp(elem, "Reference")) {
734 ptr = xp_get_string("variables", "Reference");
735
736 char ** currentTabVarName = NULL;
737 int currentNbVarNames;
738
739 createStringTable(ptr, ¤tTabVarName, ¤tNbVarNames);
740 for (int i = 0; i < currentNbVarNames; i++) {
741 int id = allocVars->find(currentTabVarName[i], false);
742 if (id == -1) {
743 ERROR("Could not reference non-existant variable '%s'", currentTabVarName[i]);
744 }
745 }
746 freeStringTable(currentTabVarName, currentNbVarNames);
747 free(ptr);
748 } else if(!strcmp(elem, "DefaultMessage")) {
749 char *id = xp_get_string("id", "DefaultMessage");
750 if(!(ptr = xp_get_cdata())) {
751 ERROR("No CDATA in 'send' section of xml scenario file");
752 }
753 char *msg = clean_cdata(ptr);
754 set_default_message(id, msg);
755 free(id);
756 /* XXX: This should really be per scenario. */
757 } else if(!strcmp(elem, "label")) {
758 ptr = xp_get_string("id", "label");
759 if (labelMap.find(ptr) != labelMap.end()) {
760 ERROR("The label name '%s' is used twice.", ptr);
761 }
762 labelMap[ptr] = messages.size();
763 free(ptr);
764 } else if (!strcmp(elem, "init")) {
765 /* We have an init section, which must be full of nops or labels. */
766 int nop_cursor = 0;
767 char *initelem;
768 while ((initelem = xp_open_element(nop_cursor++))) {
769 if (!strcmp(initelem, "nop")) {
770 /* We should parse this. */
771 message *nopmsg = new message(initmessages.size(), "scenario initialization");
772 initmessages.push_back(nopmsg);
773 nopmsg->M_type = MSG_TYPE_NOP;
774 getCommonAttributes(nopmsg);
775 } else if (!strcmp(initelem, "label")) {
776 /* Add an init label. */
777 cptr = xp_get_value("id");
778 if (initLabelMap.find(cptr) != initLabelMap.end()) {
779 ERROR("The label name '%s' is used twice.", cptr);
780 }
781 initLabelMap[cptr] = initmessages.size();
782 } else {
783 ERROR("Invalid element in an init stanza: '%s'", initelem);
784 }
785 xp_close_element();
786 }
787 } else { /** Message Case */
788 if (found_timewait) {
789 ERROR("<timewait> can only be the last message in a scenario!\n");
790 }
791 message *curmsg = new message(messages.size(), name ? name : "unknown scenario");
792 messages.push_back(curmsg);
793
794 if(!strcmp(elem, "send")) {
795 checkOptionalRecv(elem, scenario_file_cursor);
796 curmsg->M_type = MSG_TYPE_SEND;
797 /* Sent messages descriptions */
798 if(!(ptr = xp_get_cdata())) {
799 ERROR("No CDATA in 'send' section of xml scenario file");
800 }
801
802 int removed_clrf = 0;
803 char * msg = clean_cdata(ptr, &removed_clrf);
804
805 L_content_length = xp_get_content_length(msg);
806 switch (L_content_length) {
807 case -1 :
808 // the msg does not contain content-length field
809 break ;
810 case 0 :
811 curmsg -> content_length_flag =
812 message::ContentLengthValueZero; // Initialize to No present
813 break ;
814 default :
815 curmsg -> content_length_flag =
816 message::ContentLengthValueNoZero; // Initialize to No present
817 break ;
818 }
819
820 if((msg[strlen(msg) - 1] != '\n') && (removed_clrf)) {
821 strcat(msg, "\n");
822 }
823 char *tsrc = msg;
824 while(*tsrc++);
825 curmsg -> send_scheme = new SendingMessage(this, msg);
826 free(msg);
827
828 // If this is a request we are sending, then store our transaction/method matching information.
829 if (!curmsg->send_scheme->isResponse()) {
830 char *method = curmsg->send_scheme->getMethod();
831 bool isInvite = !strcmp(method, "INVITE");
832 bool isAck = !strcmp(method, "ACK");
833
834 if ((cptr = xp_get_value("start_txn"))) {
835 if (isAck) {
836 ERROR("An ACK message can not start a transaction!");
837 }
838 curmsg->start_txn = get_txn(cptr, "start transaction", true, isInvite, false);
839 } else if ((cptr = xp_get_value("ack_txn"))) {
840 if (!isAck) {
841 ERROR("The ack_txn attribute is valid only for ACK messages!");
842 }
843 curmsg->ack_txn = get_txn(cptr, "ack transaction", false, false, true);
844 } else {
845 int len = method_list ? strlen(method_list) : 0;
846 method_list = (char *)realloc(method_list, len + strlen(method) + 1);
847 if (!method_list) {
848 ERROR_NO("Out of memory allocating method_list!");
849 }
850 strcpy(method_list + len, method);
851 }
852 } else {
853 if (xp_get_value("start_txn")) {
854 ERROR("Responses can not start a transaction");
855 }
856 if (xp_get_value("ack_txn")) {
857 ERROR("Responses can not ACK a transaction");
858 }
859 }
860
861 if (xp_get_value("response_txn")) {
862 ERROR("response_txn can only be used for received messages.");
863 }
864
865 curmsg -> retrans_delay = xp_get_long("retrans", "retransmission timer", 0);
866 curmsg -> timeout = xp_get_long("timeout", "message send timeout", 0);
867 } else if (!strcmp(elem, "recv")) {
868 curmsg->M_type = MSG_TYPE_RECV;
869 /* Received messages descriptions */
870 if((cptr = xp_get_value("response"))) {
871 curmsg ->recv_response = get_long(cptr, "response code");
872 if (method_list) {
873 curmsg->recv_response_for_cseq_method_list = strdup(method_list);
874 }
875 if ((cptr = xp_get_value("response_txn"))) {
876 curmsg->response_txn = get_txn(cptr, "transaction response", false, false, false);
877 }
878 }
879
880 if ((cptr = xp_get_value("request"))) {
881 curmsg->recv_request = strdup(cptr);
882 if (xp_get_value("response_txn")) {
883 ERROR("response_txn can only be used for received responses.");
884 }
885 }
886
887 curmsg->optional = xp_get_optional("optional", "recv");
888 last_recv_optional = curmsg->optional;
889 curmsg->advance_state = xp_get_bool("advance_state", "recv", true);
890 if (!curmsg->advance_state && curmsg->optional == OPTIONAL_FALSE) {
891 ERROR("advance_state is allowed only for optional messages (index = %zu)\n", messages.size() - 1);
892 }
893
894 if ((cptr = xp_get_value("regexp_match"))) {
895 if (!strcmp(cptr, "true")) {
896 curmsg->regexp_match = 1;
897 }
898 }
899
900 curmsg->timeout = xp_get_long("timeout", "message timeout", 0);
901
902 /* record the route set */
903 /* TODO disallow optional and rrs to coexist? */
904 if ((cptr = xp_get_value("rrs"))) {
905 curmsg->bShouldRecordRoutes = get_bool(cptr, "record route set");
906 }
907
908 /* record the authentication credentials */
909 if ((cptr = xp_get_value("auth"))) {
910 bool temp = get_bool(cptr, "message authentication");
911 curmsg->bShouldAuthenticate = temp;
912 }
913 } else if(!strcmp(elem, "pause") || !strcmp(elem, "timewait")) {
914 checkOptionalRecv(elem, scenario_file_cursor);
915 curmsg->M_type = MSG_TYPE_PAUSE;
916 if (!strcmp(elem, "timewait")) {
917 curmsg->timewait = true;
918 found_timewait = true;
919 }
920
921 int var;
922 if ((var = xp_get_var("variable", "pause", -1)) != -1) {
923 curmsg->pause_variable = var;
924 } else {
925 CSample *distribution = parse_distribution(true);
926
927 bool sanity_check = xp_get_bool("sanity_check", "pause", true);
928
929 double pause_duration = distribution->cdfInv(0.99);
930 if (sanity_check && (pause_duration > INT_MAX)) {
931 char percentile[100];
932 char desc[100];
933
934 distribution->timeDescr(desc, sizeof(desc));
935 time_string(pause_duration, percentile, sizeof(percentile));
936
937 ERROR("The distribution %s has a 99th percentile of %s, which is larger than INT_MAX. You should chose different parameters.", desc, percentile);
938 }
939
940 curmsg->pause_distribution = distribution;
941 /* Update scenario duration with max duration */
942 duration += (int)pause_duration;
943 }
944 } else if(!strcmp(elem, "nop")) {
945 checkOptionalRecv(elem, scenario_file_cursor);
946 /* Does nothing at SIP level. This message type can be used to handle
947 * actions, increment counters, or for RTDs. */
948 curmsg->M_type = MSG_TYPE_NOP;
949 } else if(!strcmp(elem, "recvCmd")) {
950 curmsg->M_type = MSG_TYPE_RECVCMD;
951 curmsg->optional = xp_get_optional("optional", "recv");
952 last_recv_optional = curmsg->optional;
953
954 /* 3pcc extended mode */
955 if ((cptr = xp_get_value("src"))) {
956 curmsg->peer_src = strdup(cptr);
957 } else if (extendedTwinSippMode) {
958 ERROR("You must specify a 'src' for recvCmd when using extended 3pcc mode!");
959 }
960 } else if(!strcmp(elem, "sendCmd")) {
961 checkOptionalRecv(elem, scenario_file_cursor);
962 curmsg->M_type = MSG_TYPE_SENDCMD;
963 /* Sent messages descriptions */
964
965 /* 3pcc extended mode */
966 if ((cptr = xp_get_value("dest"))) {
967 peer = strdup(cptr);
968 curmsg->peer_dest = peer;
969 peer_map::iterator peer_it;
970 peer_it = peers.find(peer_map::key_type(peer));
971 if(peer_it == peers.end())
972 /* the peer (slave or master)
973 has not been added in the map
974 (first occurrence in the scenario) */
975 {
976 T_peer_infos infos = {};
977 infos.peer_socket = 0;
978 strncpy(infos.peer_host, get_peer_addr(peer), sizeof(infos.peer_host) - 1);
979 peers[std::string(peer)] = infos;
980 }
981 } else if (extendedTwinSippMode) {
982 ERROR("You must specify a 'dest' for sendCmd with extended 3pcc mode!");
983 }
984
985 if (!(ptr = xp_get_cdata())) {
986 ERROR("No CDATA in 'sendCmd' section of xml scenario file");
987 }
988 char *msg = clean_cdata(ptr);
989
990 curmsg -> M_sendCmdData = new SendingMessage(this, msg, true /* skip sanity */);
991 free(msg);
992 } else {
993 ERROR("Unknown element '%s' in xml scenario file", elem);
994 }
995
996 getCommonAttributes(curmsg);
997 } /** end * Message case */
998 xp_close_element();
999 } // end while
1000
1001 free(method_list);
1002
1003 str_int_map::iterator label_it = labelMap.find("_unexp.main");
1004 if (label_it != labelMap.end()) {
1005 unexpected_jump = label_it->second;
1006 } else {
1007 unexpected_jump = -1;
1008 }
1009 retaddr = find_var("_unexp.retaddr");
1010 pausedaddr = find_var("_unexp.pausedaddr");
1011
1012 /* Patch up the labels. */
1013 apply_labels(messages, labelMap);
1014 apply_labels(initmessages, initLabelMap);
1015
1016 /* Some post-scenario loading validation. */
1017 stats->validateRtds();
1018
1019 /* Make sure that all variables are used more than once. */
1020 validate_variable_usage();
1021
1022 /* Make sure that all started transactions have responses, and vice versa. */
1023 validate_txn_usage();
1024
1025 if (messages.size() == 0) {
1026 ERROR("Did not find any messages inside of scenario!");
1027 }
1028 }
1029
runInit()1030 void scenario::runInit()
1031 {
1032 call *initcall;
1033 if (initmessages.size() > 0) {
1034 initcall = new call(main_scenario, NULL, NULL, "///main-init", 0, false, false, true);
1035 initcall->run();
1036 }
1037 }
1038
clear_int_str(int_str_map m)1039 void clear_int_str(int_str_map m)
1040 {
1041 for(int_str_map::iterator it = m.begin(); it != m.end(); it = m.begin()) {
1042 free(it->second);
1043 m.erase(it);
1044 }
1045 }
1046
clear_str_int(str_int_map m)1047 void clear_str_int(str_int_map m)
1048 {
1049 for(str_int_map::iterator it = m.begin(); it != m.end(); it = m.begin()) {
1050 m.erase(it);
1051 }
1052 }
1053
clear_int_int(int_int_map m)1054 void clear_int_int(int_int_map m)
1055 {
1056 for(int_int_map::iterator it = m.begin(); it != m.end(); it = m.begin()) {
1057 m.erase(it);
1058 }
1059 }
1060
~scenario()1061 scenario::~scenario()
1062 {
1063 for (msgvec::iterator i = messages.begin(); i != messages.end(); i++) {
1064 delete *i;
1065 }
1066 messages.clear();
1067
1068 free(name);
1069
1070 allocVars->putTable();
1071 delete stats;
1072
1073 for (unsigned int i = 0; i < transactions.size(); i++) {
1074 free(transactions[i].name);
1075 }
1076 transactions.clear();
1077
1078 clear_str_int(labelMap);
1079 clear_str_int(initLabelMap);
1080 clear_str_int(txnMap);
1081 }
1082
parse_distribution(bool oldstyle=false)1083 CSample *parse_distribution(bool oldstyle = false)
1084 {
1085 CSample *distribution;
1086 const char *distname;
1087 const char *ptr = 0;
1088
1089 if(!(distname = xp_get_value("distribution"))) {
1090 if (!oldstyle) {
1091 ERROR("statistically distributed actions or pauses requires 'distribution' parameter");
1092 }
1093 if ((ptr = xp_get_value("normal"))) {
1094 distname = "normal";
1095 } else if ((ptr = xp_get_value("exponential"))) {
1096 distname = "exponential";
1097 } else if ((ptr = xp_get_value("lognormal"))) {
1098 distname = "lognormal";
1099 } else if ((ptr = xp_get_value("weibull"))) {
1100 distname = "weibull";
1101 } else if ((ptr = xp_get_value("pareto"))) {
1102 distname = "pareto";
1103 } else if ((ptr = xp_get_value("gamma"))) {
1104 distname = "gamma";
1105 } else if ((ptr = xp_get_value("min"))) {
1106 distname = "uniform";
1107 } else if ((ptr = xp_get_value("max"))) {
1108 distname = "uniform";
1109 } else if ((ptr = xp_get_value("milliseconds"))) {
1110 double val = get_double(ptr, "Pause milliseconds");
1111 return new CFixed(val);
1112 } else {
1113 return new CDefaultPause();
1114 }
1115 }
1116
1117 if (!strcmp(distname, "fixed")) {
1118 double value = xp_get_double("value", "Fixed distribution");
1119 distribution = new CFixed(value);
1120 } else if (!strcmp(distname, "uniform")) {
1121 double min = xp_get_double("min", "Uniform distribution");
1122 double max = xp_get_double("max", "Uniform distribution");
1123 distribution = new CUniform(min, max);
1124 #ifdef HAVE_GSL
1125 } else if (!strcmp(distname, "normal")) {
1126 double mean = xp_get_double("mean", "Normal distribution");
1127 double stdev = xp_get_double("stdev", "Normal distribution");
1128 distribution = new CNormal(mean, stdev);
1129 } else if (!strcmp(distname, "lognormal")) {
1130 double mean = xp_get_double("mean", "Lognormal distribution");
1131 double stdev = xp_get_double("stdev", "Lognormal distribution");
1132 distribution = new CLogNormal(mean, stdev);
1133 } else if (!strcmp(distname, "exponential")) {
1134 double mean = xp_get_double("mean", "Exponential distribution");
1135 distribution = new CExponential(mean);
1136 } else if (!strcmp(distname, "weibull")) {
1137 double lambda = xp_get_double("lambda", "Weibull distribution");
1138 double k = xp_get_double("k", "Weibull distribution");
1139 distribution = new CWeibull(lambda, k);
1140 } else if (!strcmp(distname, "pareto")) {
1141 double k = xp_get_double("k", "Pareto distribution");
1142 double xsubm = xp_get_double("x_m", "Pareto distribution");
1143 distribution = new CPareto(k, xsubm);
1144 } else if (!strcmp(distname, "gpareto")) {
1145 double shape = xp_get_double("shape", "Generalized Pareto distribution");
1146 double scale = xp_get_double("scale", "Generalized Pareto distribution");
1147 double location = xp_get_double("location", "Generalized Pareto distribution");
1148 distribution = new CGPareto(shape, scale, location);
1149 } else if (!strcmp(distname, "gamma")) {
1150 double k = xp_get_double("k", "Gamma distribution");
1151 double theta = xp_get_double("theta", "Gamma distribution");
1152 distribution = new CGamma(k, theta);
1153 } else if (!strcmp(distname, "negbin")) {
1154 double n = xp_get_double("n", "Negative Binomial distribution");
1155 double p = xp_get_double("p", "Negative Binomial distribution");
1156 distribution = new CNegBin(n, p);
1157 #else
1158 } else if (!strcmp(distname, "normal")
1159 || !strcmp(distname, "lognormal")
1160 || !strcmp(distname, "exponential")
1161 || !strcmp(distname, "pareto")
1162 || !strcmp(distname, "gamma")
1163 || !strcmp(distname, "negbin")
1164 || !strcmp(distname, "weibull")) {
1165 ERROR("The distribution '%s' is only available with GSL.", distname);
1166 #endif
1167 } else {
1168 ERROR("Unknown distribution: %s\n", ptr);
1169 }
1170
1171 return distribution;
1172 }
1173
1174
1175
1176 /* 3pcc extended mode:
1177 get the correspondances between
1178 slave and master names and their
1179 addresses */
1180
parse_slave_cfg()1181 void parse_slave_cfg()
1182 {
1183 FILE * f;
1184 char line[MAX_PEER_SIZE];
1185 char * temp_peer;
1186 char * temp_host;
1187 char * peer_host;
1188
1189 f = fopen(slave_cfg_file, "r");
1190 if(f) {
1191 while (fgets(line, MAX_PEER_SIZE, f) != NULL) {
1192 temp_peer = strtok(line, ";");
1193 if (!temp_peer)
1194 continue;
1195
1196 temp_host = strtok(NULL, ";");
1197 if (!temp_host)
1198 continue;
1199
1200 peer_host = strdup(temp_host);
1201 if (!peer_host)
1202 ERROR("Cannot allocate memory!\n");
1203
1204 peer_addrs[std::string(temp_peer)] = peer_host;
1205 }
1206 } else {
1207 ERROR("Can not open slave_cfg file %s\n", slave_cfg_file);
1208 }
1209
1210 fclose(f);
1211 }
1212
1213 // Determine in which mode the sipp tool has been
1214 // launched (client, server, 3pcc client, 3pcc server, 3pcc extended master or slave)
computeSippMode()1215 void scenario::computeSippMode()
1216 {
1217 bool isRecvCmdFound = false;
1218 bool isSendCmdFound = false;
1219
1220 creationMode = -1;
1221 sendMode = -1;
1222 thirdPartyMode = MODE_3PCC_NONE;
1223
1224 assert(messages.size() > 0);
1225
1226 for(unsigned int i=0; i<messages.size(); i++) {
1227 switch(messages[i]->M_type) {
1228 case MSG_TYPE_PAUSE:
1229 case MSG_TYPE_NOP:
1230 /* Allow pauses or nops to go first. */
1231 continue;
1232 case MSG_TYPE_SEND:
1233 if (sendMode == -1) {
1234 sendMode = MODE_CLIENT;
1235 }
1236 if (creationMode == -1) {
1237 creationMode = MODE_CLIENT;
1238 }
1239 break;
1240
1241 case MSG_TYPE_RECV:
1242 if (sendMode == -1) {
1243 sendMode = MODE_SERVER;
1244 }
1245 if (creationMode == -1) {
1246 creationMode = MODE_SERVER;
1247 }
1248 break;
1249 case MSG_TYPE_SENDCMD:
1250 isSendCmdFound = true;
1251 if (creationMode == -1) {
1252 creationMode = MODE_CLIENT;
1253 }
1254 if(!isRecvCmdFound) {
1255 if (creationMode == MODE_SERVER) {
1256 /*
1257 * If it is a server already, then start it in
1258 * 3PCC A passive mode
1259 */
1260 if(twinSippMode) {
1261 thirdPartyMode = MODE_3PCC_A_PASSIVE;
1262 } else if (extendedTwinSippMode) {
1263 thirdPartyMode = MODE_MASTER_PASSIVE;
1264 }
1265 } else {
1266 if(twinSippMode) {
1267 thirdPartyMode = MODE_3PCC_CONTROLLER_A;
1268 } else if (extendedTwinSippMode) {
1269 thirdPartyMode = MODE_MASTER;
1270 }
1271 }
1272 if((thirdPartyMode == MODE_MASTER_PASSIVE || thirdPartyMode == MODE_MASTER) && !master_name) {
1273 ERROR("Inconsistency between command line and scenario: master scenario but -master option not set\n");
1274 }
1275 if(!twinSippMode && !extendedTwinSippMode)
1276 ERROR("sendCmd message found in scenario but no twin sipp"
1277 " address has been passed! Use -3pcc option or 3pcc extended mode.\n");
1278 }
1279 break;
1280
1281 case MSG_TYPE_RECVCMD:
1282 if (creationMode == -1) {
1283 creationMode = MODE_SERVER;
1284 }
1285 isRecvCmdFound = true;
1286 if(!isSendCmdFound) {
1287 if(twinSippMode) {
1288 thirdPartyMode = MODE_3PCC_CONTROLLER_B;
1289 } else if(extendedTwinSippMode) {
1290 thirdPartyMode = MODE_SLAVE;
1291 if(!slave_number) {
1292 ERROR("Inconsistency between command line and scenario: slave scenario but -slave option not set\n");
1293 } else {
1294 thirdPartyMode = MODE_SLAVE;
1295 }
1296 }
1297 if(!twinSippMode && !extendedTwinSippMode)
1298 ERROR("recvCmd message found in scenario but no "
1299 "twin sipp address has been passed! Use "
1300 "-3pcc option\n");
1301 }
1302 break;
1303 default:
1304 break;
1305 }
1306 }
1307 if(creationMode == -1)
1308 ERROR("Unable to determine creation mode of the tool (server, client)\n");
1309 if(sendMode == -1)
1310 ERROR("Unable to determine send mode of the tool (server, client)\n");
1311 }
1312
handle_rhs(CAction * tmpAction,const char * what)1313 void scenario::handle_rhs(CAction *tmpAction, const char *what)
1314 {
1315 if (xp_get_value("value")) {
1316 tmpAction->setDoubleValue(xp_get_double("value", what));
1317 if (xp_get_value("variable")) {
1318 ERROR("Value and variable are mutually exclusive for %s action!", what);
1319 }
1320 } else if (xp_get_value("variable")) {
1321 tmpAction->setVarInId(xp_get_var("variable", what));
1322 if (xp_get_value("value")) {
1323 ERROR("Value and variable are mutually exclusive for %s action!", what);
1324 }
1325 } else {
1326 ERROR("No value or variable defined for %s action!", what);
1327 }
1328 }
1329
handle_arithmetic(CAction * tmpAction,const char * what)1330 void scenario::handle_arithmetic(CAction *tmpAction, const char *what)
1331 {
1332 tmpAction->setVarId(xp_get_var("assign_to", what));
1333 handle_rhs(tmpAction, what);
1334 }
1335
parseAction(CActions * actions)1336 void scenario::parseAction(CActions *actions)
1337 {
1338 char * actionElem;
1339 unsigned int recvScenarioLen = 0;
1340 char * currentRegExp = NULL;
1341 char ** currentTabVarName = NULL;
1342 int currentNbVarNames;
1343 int sub_currentNbVarId;
1344 char* ptr;
1345 const char* cptr;
1346
1347 while((actionElem = xp_open_element(recvScenarioLen))) {
1348 CAction *tmpAction = new CAction(this);
1349
1350 if(!strcmp(actionElem, "ereg")) {
1351 ptr = xp_get_string("regexp", "ereg");
1352
1353 // keeping regexp expression in memory
1354 if(currentRegExp != NULL)
1355 delete[] currentRegExp;
1356 currentRegExp = new char[strlen(ptr)+1];
1357 xp_unescape(ptr, currentRegExp);
1358 tmpAction->setActionType(CAction::E_AT_ASSIGN_FROM_REGEXP);
1359
1360 // warning - although these are detected for both msg and hdr
1361 // they are only implemented for search_in="hdr"
1362 tmpAction->setCaseIndep(xp_get_bool("case_indep", "ereg", false));
1363 tmpAction->setHeadersOnly(xp_get_bool("start_line", "ereg", false));
1364
1365 free(ptr);
1366 if ((cptr = xp_get_value("search_in"))) {
1367 tmpAction->setOccurrence(1);
1368
1369 if (strcmp(cptr, "msg") == 0) {
1370 tmpAction->setLookingPlace(CAction::E_LP_MSG);
1371 tmpAction->setLookingChar (NULL);
1372 } else if (strcmp(cptr, "body") == 0) {
1373 tmpAction->setLookingPlace(CAction::E_LP_BODY);
1374 tmpAction->setLookingChar (NULL);
1375 } else if (strcmp(cptr, "var") == 0) {
1376 tmpAction->setVarInId(xp_get_var("variable", "ereg"));
1377 tmpAction->setLookingPlace(CAction::E_LP_VAR);
1378 } else if (strcmp(cptr, "hdr") == 0) {
1379 cptr = xp_get_value("header");
1380 if (!cptr || !strlen(cptr)) {
1381 ERROR("search_in=\"hdr\" requires header field");
1382 }
1383 tmpAction->setLookingPlace(CAction::E_LP_HDR);
1384 tmpAction->setLookingChar(cptr);
1385 if ((cptr = xp_get_value("occurrence"))) {
1386 tmpAction->setOccurrence(atol(cptr));
1387 } else if ((cptr = xp_get_value("occurence"))) {
1388 /* old misspelling */
1389 tmpAction->setOccurrence(atol(cptr));
1390 }
1391 } else {
1392 ERROR("Unknown search_in value %s", cptr);
1393 }
1394 } else {
1395 tmpAction->setLookingPlace(CAction::E_LP_MSG);
1396 tmpAction->setLookingChar(NULL);
1397 } // end if-else search_in
1398
1399 if (xp_get_value("check_it")) {
1400 tmpAction->setCheckIt(xp_get_bool("check_it", "ereg", false));
1401 if (xp_get_value("check_it_inverse")) {
1402 ERROR("Can not have both check_it and check_it_inverse for ereg!");
1403 }
1404 } else {
1405 tmpAction->setCheckItInverse(xp_get_bool("check_it_inverse", "ereg", false));
1406 }
1407
1408 if (!(ptr = xp_get_value("assign_to"))) {
1409 ERROR("assign_to value is missing");
1410 }
1411
1412 createStringTable(ptr, ¤tTabVarName, ¤tNbVarNames);
1413
1414 int varId = get_var(currentTabVarName[0], "assign_to");
1415 tmpAction->setVarId(varId);
1416
1417 tmpAction->setRegExp(currentRegExp);
1418 if (currentNbVarNames > 1 ) {
1419 sub_currentNbVarId = currentNbVarNames - 1 ;
1420 tmpAction->setNbSubVarId(sub_currentNbVarId);
1421
1422 for(int i=1; i<= sub_currentNbVarId; i++) {
1423 int varId = get_var(currentTabVarName[i], "sub expression assign_to");
1424 tmpAction->setSubVarId(varId);
1425 }
1426 }
1427
1428 freeStringTable(currentTabVarName, currentNbVarNames);
1429
1430 if(currentRegExp != NULL) {
1431 delete[] currentRegExp;
1432 }
1433 currentRegExp = NULL;
1434 } /* end !strcmp(actionElem, "ereg") */ else if(!strcmp(actionElem, "log")) {
1435 ptr = xp_get_string("message", "log");
1436 tmpAction->setMessage(ptr);
1437 free(ptr);
1438 tmpAction->setActionType(CAction::E_AT_LOG_TO_FILE);
1439 } else if(!strcmp(actionElem, "warning")) {
1440 ptr = xp_get_string("message", "warning");
1441 tmpAction->setMessage(ptr);
1442 free(ptr);
1443 tmpAction->setActionType(CAction::E_AT_LOG_WARNING);
1444 } else if(!strcmp(actionElem, "error")) {
1445 ptr = xp_get_string("message", "error");
1446 tmpAction->setMessage(ptr);
1447 free(ptr);
1448 tmpAction->setActionType(CAction::E_AT_LOG_ERROR);
1449 } else if(!strcmp(actionElem, "assign")) {
1450 tmpAction->setActionType(CAction::E_AT_ASSIGN_FROM_VALUE);
1451 handle_arithmetic(tmpAction, "assign");
1452 } else if(!strcmp(actionElem, "assignstr")) {
1453 tmpAction->setActionType(CAction::E_AT_ASSIGN_FROM_STRING);
1454 tmpAction->setVarId(xp_get_var("assign_to", "assignstr"));
1455 ptr = xp_get_string("value", "assignstr");
1456 tmpAction->setMessage(ptr);
1457 free(ptr);
1458 } else if(!strcmp(actionElem, "gettimeofday")) {
1459 tmpAction->setActionType(CAction::E_AT_ASSIGN_FROM_GETTIMEOFDAY);
1460
1461 if (!(ptr = xp_get_value("assign_to"))) {
1462 ERROR("assign_to value is missing");
1463 }
1464 createStringTable(ptr, ¤tTabVarName, ¤tNbVarNames);
1465 if (currentNbVarNames != 2 ) {
1466 ERROR("The gettimeofday action requires two output variables!");
1467 }
1468 tmpAction->setNbSubVarId(1);
1469
1470 int varId = get_var(currentTabVarName[0], "gettimeofday seconds assign_to");
1471 tmpAction->setVarId(varId);
1472 varId = get_var(currentTabVarName[1], "gettimeofday useconds assign_to");
1473 tmpAction->setSubVarId(varId);
1474
1475 freeStringTable(currentTabVarName, currentNbVarNames);
1476 } else if(!strcmp(actionElem, "index")) {
1477 tmpAction->setVarId(xp_get_var("assign_to", "index"));
1478 tmpAction->setActionType(CAction::E_AT_ASSIGN_FROM_INDEX);
1479 } else if(!strcmp(actionElem, "jump")) {
1480 tmpAction->setActionType(CAction::E_AT_JUMP);
1481 handle_rhs(tmpAction, "jump");
1482 } else if(!strcmp(actionElem, "pauserestore")) {
1483 tmpAction->setActionType(CAction::E_AT_PAUSE_RESTORE);
1484 handle_rhs(tmpAction, "pauserestore");
1485 } else if(!strcmp(actionElem, "add")) {
1486 tmpAction->setActionType(CAction::E_AT_VAR_ADD);
1487 handle_arithmetic(tmpAction, "add");
1488 } else if(!strcmp(actionElem, "subtract")) {
1489 tmpAction->setActionType(CAction::E_AT_VAR_SUBTRACT);
1490 handle_arithmetic(tmpAction, "subtract");
1491 } else if(!strcmp(actionElem, "multiply")) {
1492 tmpAction->setActionType(CAction::E_AT_VAR_MULTIPLY);
1493 handle_arithmetic(tmpAction, "multiply");
1494 } else if(!strcmp(actionElem, "divide")) {
1495 tmpAction->setActionType(CAction::E_AT_VAR_DIVIDE);
1496 handle_arithmetic(tmpAction, "divide");
1497 if (tmpAction->getVarInId() == 0) {
1498 if (tmpAction->getDoubleValue() == 0.0) {
1499 ERROR("divide actions can not have a value of zero!");
1500 }
1501 }
1502 } else if(!strcmp(actionElem, "sample")) {
1503 tmpAction->setVarId(xp_get_var("assign_to", "sample"));
1504 tmpAction->setActionType(CAction::E_AT_ASSIGN_FROM_SAMPLE);
1505 tmpAction->setDistribution(parse_distribution());
1506 } else if(!strcmp(actionElem, "todouble")) {
1507 tmpAction->setActionType(CAction::E_AT_VAR_TO_DOUBLE);
1508 tmpAction->setVarId(xp_get_var("assign_to", "todouble"));
1509 tmpAction->setVarInId(xp_get_var("variable", "todouble"));
1510 } else if(!strcmp(actionElem, "test")) {
1511 tmpAction->setVarId(xp_get_var("assign_to", "test"));
1512 tmpAction->setVarInId(xp_get_var("variable", "test"));
1513 if (xp_get_value("value")) {
1514 tmpAction->setDoubleValue(xp_get_double("value", "test"));
1515 if (xp_get_value("variable2")) {
1516 ERROR("Can not have both a value and a variable2 for test!");
1517 }
1518 } else {
1519 tmpAction->setVarIn2Id(xp_get_var("variable2", "test"));
1520 }
1521 tmpAction->setActionType(CAction::E_AT_VAR_TEST);
1522 ptr = xp_get_string("compare", "test");
1523 if (!strcmp(ptr, "equal")) {
1524 tmpAction->setComparator(CAction::E_C_EQ);
1525 } else if (!strcmp(ptr, "not_equal")) {
1526 tmpAction->setComparator(CAction::E_C_NE);
1527 } else if (!strcmp(ptr, "greater_than")) {
1528 tmpAction->setComparator(CAction::E_C_GT);
1529 } else if (!strcmp(ptr, "less_than")) {
1530 tmpAction->setComparator(CAction::E_C_LT);
1531 } else if (!strcmp(ptr, "greater_than_equal")) {
1532 tmpAction->setComparator(CAction::E_C_GEQ);
1533 } else if (!strcmp(ptr, "less_than_equal")) {
1534 tmpAction->setComparator(CAction::E_C_LEQ);
1535 } else {
1536 ERROR("Invalid 'compare' parameter: %s", ptr);
1537 }
1538 free(ptr);
1539 } else if(!strcmp(actionElem, "verifyauth")) {
1540 tmpAction->setVarId(xp_get_var("assign_to", "verifyauth"));
1541 char* username_ptr = xp_get_string("username", "verifyauth");
1542 char* password_ptr = xp_get_string("password", "verifyauth");
1543 tmpAction->setMessage(username_ptr, 0);
1544 tmpAction->setMessage(password_ptr, 1);
1545 tmpAction->setActionType(CAction::E_AT_VERIFY_AUTH);
1546 free(username_ptr);
1547 free(password_ptr);
1548 username_ptr = password_ptr = NULL;
1549 } else if(!strcmp(actionElem, "lookup")) {
1550 tmpAction->setVarId(xp_get_var("assign_to", "lookup"));
1551 tmpAction->setMessage(xp_get_string("file", "lookup"), 0);
1552 tmpAction->setMessage(xp_get_string("key", "lookup"), 1);
1553 tmpAction->setActionType(CAction::E_AT_LOOKUP);
1554 } else if(!strcmp(actionElem, "insert")) {
1555 tmpAction->setMessage(xp_get_string("file", "insert"), 0);
1556 tmpAction->setMessage(xp_get_string("value", "insert"), 1);
1557 tmpAction->setActionType(CAction::E_AT_INSERT);
1558 } else if(!strcmp(actionElem, "replace")) {
1559 tmpAction->setMessage(xp_get_string("file", "replace"), 0);
1560 tmpAction->setMessage(xp_get_string("line", "replace"), 1);
1561 tmpAction->setMessage(xp_get_string("value", "replace"), 2);
1562 tmpAction->setActionType(CAction::E_AT_REPLACE);
1563 } else if(!strcmp(actionElem, "setdest")) {
1564 tmpAction->setMessage(xp_get_string("host", actionElem), 0);
1565 tmpAction->setMessage(xp_get_string("port", actionElem), 1);
1566 tmpAction->setMessage(xp_get_string("protocol", actionElem), 2);
1567 tmpAction->setActionType(CAction::E_AT_SET_DEST);
1568 } else if(!strcmp(actionElem, "closecon")) {
1569 tmpAction->setActionType(CAction::E_AT_CLOSE_CON);
1570 } else if(!strcmp(actionElem, "strcmp")) {
1571 tmpAction->setVarId(xp_get_var("assign_to", "strcmp"));
1572 tmpAction->setVarInId(xp_get_var("variable", "strcmp"));
1573 if (xp_get_value("value")) {
1574 tmpAction->setStringValue(xp_get_string("value", "strcmp"));
1575 if (xp_get_value("variable2")) {
1576 ERROR("Can not have both a value and a variable2 for strcmp!");
1577 }
1578 } else {
1579 tmpAction->setVarIn2Id(xp_get_var("variable2", "strcmp"));
1580 }
1581 tmpAction->setActionType(CAction::E_AT_VAR_STRCMP);
1582 } else if(!strcmp(actionElem, "trim")) {
1583 tmpAction->setVarId(xp_get_var("assign_to", "trim"));
1584 tmpAction->setActionType(CAction::E_AT_VAR_TRIM);
1585 } else if(!strcmp(actionElem, "exec")) {
1586 if ((ptr = xp_get_value("command"))) {
1587 tmpAction->setActionType(CAction::E_AT_EXECUTE_CMD);
1588 tmpAction->setMessage(ptr);
1589 } else if((cptr = xp_get_value("int_cmd"))) {
1590 CAction::T_IntCmdType type(CAction::E_INTCMD_STOPCALL); /* assume the default */
1591
1592 if (strcmp(cptr, "stop_now") == 0) {
1593 type = CAction::E_INTCMD_STOP_NOW;
1594 } else if (strcmp(cptr, "stop_gracefully") == 0) {
1595 type = CAction::E_INTCMD_STOP_ALL;
1596 } else if (strcmp(cptr, "stop_call") == 0) {
1597 type = CAction::E_INTCMD_STOPCALL;
1598 }
1599
1600 /* the action is well formed, adding it in the */
1601 /* tmpActionTable */
1602 tmpAction->setActionType(CAction::E_AT_EXEC_INTCMD);
1603 tmpAction->setIntCmd(type);
1604 #ifdef PCAPPLAY
1605 } else if ((cptr = xp_get_keyword_value("play_pcap_audio"))) {
1606 tmpAction->setPcapArgs(cptr);
1607 tmpAction->setActionType(CAction::E_AT_PLAY_PCAP_AUDIO);
1608 hasMedia = 1;
1609 } else if ((cptr = xp_get_keyword_value("play_pcap_image"))) {
1610 tmpAction->setPcapArgs(cptr);
1611 tmpAction->setActionType(CAction::E_AT_PLAY_PCAP_IMAGE);
1612 hasMedia = 1;
1613 } else if ((cptr = xp_get_keyword_value("play_pcap_video"))) {
1614 tmpAction->setPcapArgs(cptr);
1615 tmpAction->setActionType(CAction::E_AT_PLAY_PCAP_VIDEO);
1616 hasMedia = 1;
1617 #else
1618 } else if (xp_get_value("play_pcap_audio")) {
1619 ERROR("Scenario specifies a play_pcap_audio action, but this version of SIPp does not have PCAP support");
1620 } else if (xp_get_value("play_pcap_image")) {
1621 ERROR("Scenario specifies a play_pcap_image action, but this version of SIPp does not have PCAP support");
1622 } else if (xp_get_value("play_pcap_video")) {
1623 ERROR("Scenario specifies a play_pcap_video action, but this version of SIPp does not have PCAP support");
1624 #endif
1625 } else if ((cptr = xp_get_value("rtp_stream"))) {
1626 #ifdef RTP_STREAM
1627 hasMedia = 1;
1628 if (strcmp(cptr, "pause") == 0) {
1629 tmpAction->setActionType(CAction::E_AT_RTP_STREAM_PAUSE);
1630 } else if (strcmp(cptr, "resume") == 0) {
1631 tmpAction->setActionType(CAction::E_AT_RTP_STREAM_RESUME);
1632 } else {
1633 tmpAction->setRTPStreamActInfo(cptr);
1634 tmpAction->setActionType(CAction::E_AT_RTP_STREAM_PLAY);
1635 }
1636 #else
1637 ERROR("Scenario specifies a rtp_stream action, but this version of SIPp does not have RTP stream support");
1638 #endif
1639 } else {
1640 ERROR("illegal <exec> in the scenario\n");
1641 }
1642 } else {
1643 ERROR("Unknown action: %s", actionElem);
1644 }
1645
1646 /* If the action was not well-formed, there should have already been an
1647 * ERROR declaration, thus it is safe to add it here at the end of the loop. */
1648 actions->setAction(tmpAction);
1649
1650 xp_close_element();
1651 recvScenarioLen++;
1652 } // end while
1653 }
1654
1655 // Action list for the message indexed by message_index in
1656 // the scenario
getActionForThisMessage(message * message)1657 void scenario::getActionForThisMessage(message *message)
1658 {
1659 char * actionElem;
1660
1661 if(!(actionElem = xp_open_element(0))) {
1662 return;
1663 }
1664 if(strcmp(actionElem, "action")) {
1665 return;
1666 }
1667
1668 /* We actually have an action element. */
1669 if(message->M_actions != NULL) {
1670 ERROR("Duplicate action for %s index %d", message->desc, message->index);
1671 }
1672 message->M_actions = new CActions();
1673
1674 parseAction(message->M_actions);
1675 xp_close_element();
1676 }
1677
getBookKeeping(message * message)1678 void scenario::getBookKeeping(message *message)
1679 {
1680 const char *ptr;
1681
1682 if ((ptr = xp_get_value("rtd"))) {
1683 message->stop_rtd = get_rtd(ptr, false);
1684 }
1685 if ((ptr = xp_get_value("repeat_rtd"))) {
1686 if (message->stop_rtd) {
1687 message->repeat_rtd = get_bool(ptr, "repeat_rtd");
1688 } else {
1689 ERROR("There is a repeat_rtd element without an rtd element");
1690 }
1691 }
1692
1693 if ((ptr = xp_get_value("start_rtd"))) {
1694 message->start_rtd = get_rtd(ptr, true);
1695 }
1696
1697 if ((ptr = xp_get_value("counter"))) {
1698 message->counter = get_counter(ptr, "counter");
1699 }
1700 }
1701
getCommonAttributes(message * message)1702 void scenario::getCommonAttributes(message *message)
1703 {
1704 char *ptr;
1705
1706 getBookKeeping(message);
1707 getActionForThisMessage(message);
1708
1709 if((ptr = xp_get_value((char *)"lost"))) {
1710 message -> lost = get_double(ptr, "lost percentage");
1711 lose_packets = 1;
1712 }
1713
1714 if((ptr = xp_get_value((char *)"crlf"))) {
1715 message -> crlf = 1;
1716 }
1717
1718 if (xp_get_value("hiderest")) {
1719 hidedefault = xp_get_bool("hiderest", "hiderest");
1720 }
1721 message -> hide = xp_get_bool("hide", "hide", hidedefault);
1722 if((ptr = xp_get_value((char *)"display"))) {
1723 message -> display_str = strdup(ptr);
1724 }
1725
1726 message -> condexec = xp_get_var("condexec", "condexec variable", -1);
1727 message -> condexec_inverse = xp_get_bool("condexec_inverse", "condexec_inverse", false);
1728
1729 if ((ptr = xp_get_value("next"))) {
1730 if (found_timewait) {
1731 ERROR("next labels are not allowed in <timewait> elements.");
1732 }
1733 message->nextLabel = strdup(ptr);
1734 message->test = xp_get_var("test", "test variable", -1);
1735 if ( 0 != ( ptr = xp_get_value((char *)"chance") ) ) {
1736 float chance = get_double(ptr,"chance");
1737 /* probability of branch to next */
1738 if (( chance < 0.0 ) || (chance > 1.0 )) {
1739 ERROR("Chance %s not in range [0..1]", ptr);
1740 }
1741 message -> chance = (int)((1.0-chance)*RAND_MAX);
1742 } else {
1743 message -> chance = 0; /* always */
1744 }
1745 }
1746
1747 if ((ptr = xp_get_value((char *)"ontimeout"))) {
1748 if (found_timewait) {
1749 ERROR("ontimeout labels are not allowed in <timewait> elements.");
1750 }
1751 message -> onTimeoutLabel = strdup(ptr);
1752 }
1753 }
1754
1755 // char* manipulation : create a int[] from a char*
1756 // test first is the char* is formed by int separeted by coma
1757 // and then create the table
1758
isWellFormed(char * P_listeStr,int * nombre)1759 int isWellFormed(char * P_listeStr, int * nombre)
1760 {
1761 char * ptr = P_listeStr;
1762 int sizeOf;
1763 bool isANumber;
1764
1765 (*nombre) = 0;
1766 sizeOf = strlen(P_listeStr);
1767 // getting the number
1768 if(sizeOf > 0) {
1769 // is the string well formed ? [0-9] [,]
1770 isANumber = false;
1771 for(int i=0; i<=sizeOf; i++) {
1772 switch(ptr[i]) {
1773 case ',':
1774 if(isANumber == false) {
1775 return(0);
1776 } else {
1777 (*nombre)++;
1778 }
1779 isANumber = false;
1780 break;
1781 case '0':
1782 case '1':
1783 case '2':
1784 case '3':
1785 case '4':
1786 case '5':
1787 case '6':
1788 case '7':
1789 case '8':
1790 case '9':
1791 isANumber = true;
1792 break;
1793 case '\t':
1794 case ' ' :
1795 break;
1796 case '\0':
1797 if(isANumber == false) {
1798 return(0);
1799 } else {
1800 (*nombre)++;
1801 }
1802 break;
1803 default:
1804 return(0);
1805 }
1806 } // end for
1807 }
1808 return(1);
1809 }
1810
createIntegerTable(char * P_listeStr,unsigned int ** listeInteger,int * sizeOfList)1811 int createIntegerTable(char * P_listeStr,
1812 unsigned int ** listeInteger,
1813 int * sizeOfList)
1814 {
1815 int nb=0;
1816 char * ptr = P_listeStr;
1817 char * ptr_prev = P_listeStr;
1818 unsigned int current_int;
1819
1820 if(P_listeStr) {
1821 if(isWellFormed(P_listeStr, sizeOfList) == 1) {
1822 (*listeInteger) = new unsigned int[(*sizeOfList)];
1823 while((*ptr) != ('\0')) {
1824 if((*ptr) == ',') {
1825 sscanf(ptr_prev, "%u", ¤t_int);
1826 if (nb<(*sizeOfList))
1827 (*listeInteger)[nb] = current_int;
1828 nb++;
1829 ptr_prev = ptr+1;
1830 }
1831 ptr++;
1832 }
1833
1834 // Read the last
1835 sscanf(ptr_prev, "%u", ¤t_int);
1836 if (nb<(*sizeOfList))
1837 (*listeInteger)[nb] = current_int;
1838 nb++;
1839 return(1);
1840 }
1841 return(0);
1842 } else return(0);
1843 }
1844
createStringTable(char * inputString,char *** stringList,int * sizeOfList)1845 int createStringTable(char * inputString, char *** stringList, int *sizeOfList)
1846 {
1847 if(!inputString) {
1848 return 0;
1849 }
1850
1851 *stringList = NULL;
1852 *sizeOfList = 0;
1853
1854 do {
1855 char *p = strchr(inputString, ',');
1856 if (p) {
1857 *p++ = '\0';
1858 }
1859
1860 *stringList = (char **)realloc(*stringList, sizeof(char *) * (*sizeOfList + 1));
1861 (*stringList)[*sizeOfList] = strdup(inputString);
1862 (*sizeOfList)++;
1863
1864 inputString = p;
1865 } while (inputString);
1866
1867 return 1;
1868 }
1869
freeStringTable(char ** stringList,int sizeOfList)1870 void freeStringTable(char ** stringList, int sizeOfList)
1871 {
1872 for (int i = 0; i < sizeOfList; i++) {
1873 free(stringList[i]);
1874 }
1875 free(stringList);
1876 }
1877
1878 /* These are the names of the scenarios, they must match the default_scenario table. */
1879 const char *scenario_table[] = {
1880 "uac",
1881 "uas",
1882 "regexp",
1883 "3pcc-C-A",
1884 "3pcc-C-B",
1885 "3pcc-A",
1886 "3pcc-B",
1887 "branchc",
1888 "branchs",
1889 "uac_pcap",
1890 "ooc_default",
1891 "ooc_dummy",
1892 };
1893
find_scenario(const char * scenario)1894 int find_scenario(const char *scenario)
1895 {
1896 int i, max;
1897 max = sizeof(scenario_table)/sizeof(scenario_table[0]);
1898
1899 for (i = 0; i < max; i++) {
1900 if (!strcmp(scenario_table[i], scenario)) {
1901 return i;
1902 }
1903 }
1904
1905 ERROR("Invalid default scenario name '%s'.\n", scenario);
1906 return -1;
1907 }
1908
1909 // TIP: to integrate an existing XML scenario, use the following sed line:
1910 // cat ../3pcc-controller-B.xml | sed -e 's/\"/\\\"/g' -e 's/\(.*\)/\"\1\\n\"/'
1911 const char * default_scenario [] = {
1912 /************* Default_scenario[0] ***************/
1913 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n"
1914 "<!DOCTYPE scenario SYSTEM \"sipp.dtd\">\n"
1915 "\n"
1916 "<!-- This program is free software; you can redistribute it and/or -->\n"
1917 "<!-- modify it under the terms of the GNU General Public License as -->\n"
1918 "<!-- published by the Free Software Foundation; either version 2 of the -->\n"
1919 "<!-- License, or (at your option) any later version. -->\n"
1920 "<!-- -->\n"
1921 "<!-- This program is distributed in the hope that it will be useful, -->\n"
1922 "<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->\n"
1923 "<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->\n"
1924 "<!-- GNU General Public License for more details. -->\n"
1925 "<!-- -->\n"
1926 "<!-- You should have received a copy of the GNU General Public License -->\n"
1927 "<!-- along with this program; if not, write to the -->\n"
1928 "<!-- Free Software Foundation, Inc., -->\n"
1929 "<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->\n"
1930 "<!-- -->\n"
1931 "<!-- Sipp default 'uac' scenario. -->\n"
1932 "<!-- -->\n"
1933 "\n"
1934 "<scenario name=\"Basic Sipstone UAC\">\n"
1935 " <!-- In client mode (sipp placing calls), the Call-ID MUST be -->\n"
1936 " <!-- generated by sipp. To do so, use [call_id] keyword. -->\n"
1937 " <send retrans=\"500\">\n"
1938 " <![CDATA[\n"
1939 "\n"
1940 " INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"
1941 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
1942 " From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]\n"
1943 " To: [service] <sip:[service]@[remote_ip]:[remote_port]>\n"
1944 " Call-ID: [call_id]\n"
1945 " CSeq: 1 INVITE\n"
1946 " Contact: sip:sipp@[local_ip]:[local_port]\n"
1947 " Max-Forwards: 70\n"
1948 " Subject: Performance Test\n"
1949 " Content-Type: application/sdp\n"
1950 " Content-Length: [len]\n"
1951 "\n"
1952 " v=0\n"
1953 " o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]\n"
1954 " s=-\n"
1955 " c=IN IP[media_ip_type] [media_ip]\n"
1956 " t=0 0\n"
1957 " m=audio [media_port] RTP/AVP 0\n"
1958 " a=rtpmap:0 PCMU/8000\n"
1959 "\n"
1960 " ]]>\n"
1961 " </send>\n"
1962 "\n"
1963 " <recv response=\"100\"\n"
1964 " optional=\"true\">\n"
1965 " </recv>\n"
1966 "\n"
1967 " <recv response=\"180\" optional=\"true\">\n"
1968 " </recv>\n"
1969 "\n"
1970 " <recv response=\"183\" optional=\"true\">\n"
1971 " </recv>\n"
1972 "\n"
1973 " <!-- By adding rrs=\"true\" (Record Route Sets), the route sets -->\n"
1974 " <!-- are saved and used for following messages sent. Useful to test -->\n"
1975 " <!-- against stateful SIP proxies/B2BUAs. -->\n"
1976 " <recv response=\"200\" rtd=\"true\">\n"
1977 " </recv>\n"
1978 "\n"
1979 " <!-- Packet lost can be simulated in any send/recv message by -->\n"
1980 " <!-- by adding the 'lost = \"10\"'. Value can be [1-100] percent. -->\n"
1981 " <send>\n"
1982 " <![CDATA[\n"
1983 "\n"
1984 " ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"
1985 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
1986 " From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]\n"
1987 " To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n"
1988 " Call-ID: [call_id]\n"
1989 " CSeq: 1 ACK\n"
1990 " Contact: sip:sipp@[local_ip]:[local_port]\n"
1991 " Max-Forwards: 70\n"
1992 " Subject: Performance Test\n"
1993 " Content-Length: 0\n"
1994 "\n"
1995 " ]]>\n"
1996 " </send>\n"
1997 "\n"
1998 " <!-- This delay can be customized by the -d command-line option -->\n"
1999 " <!-- or by adding a 'milliseconds = \"value\"' option here. -->\n"
2000 " <pause/>\n"
2001 "\n"
2002 " <!-- The 'crlf' option inserts a blank line in the statistics report. -->\n"
2003 " <send retrans=\"500\">\n"
2004 " <![CDATA[\n"
2005 "\n"
2006 " BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"
2007 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
2008 " From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]\n"
2009 " To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n"
2010 " Call-ID: [call_id]\n"
2011 " CSeq: 2 BYE\n"
2012 " Contact: sip:sipp@[local_ip]:[local_port]\n"
2013 " Max-Forwards: 70\n"
2014 " Subject: Performance Test\n"
2015 " Content-Length: 0\n"
2016 "\n"
2017 " ]]>\n"
2018 " </send>\n"
2019 "\n"
2020 " <recv response=\"200\" crlf=\"true\">\n"
2021 " </recv>\n"
2022 "\n"
2023 " <!-- definition of the response time repartition table (unit is ms) -->\n"
2024 " <ResponseTimeRepartition value=\"10, 20, 30, 40, 50, 100, 150, 200\"/>\n"
2025 "\n"
2026 " <!-- definition of the call length repartition table (unit is ms) -->\n"
2027 " <CallLengthRepartition value=\"10, 50, 100, 500, 1000, 5000, 10000\"/>\n"
2028 "\n"
2029 "</scenario>\n"
2030 "\n"
2031 ,
2032
2033 /************* Default_scenario[1] ***************/
2034 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n"
2035 "<!DOCTYPE scenario SYSTEM \"sipp.dtd\">\n"
2036 "\n"
2037 "<!-- This program is free software; you can redistribute it and/or -->\n"
2038 "<!-- modify it under the terms of the GNU General Public License as -->\n"
2039 "<!-- published by the Free Software Foundation; either version 2 of the -->\n"
2040 "<!-- License, or (at your option) any later version. -->\n"
2041 "<!-- -->\n"
2042 "<!-- This program is distributed in the hope that it will be useful, -->\n"
2043 "<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->\n"
2044 "<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->\n"
2045 "<!-- GNU General Public License for more details. -->\n"
2046 "<!-- -->\n"
2047 "<!-- You should have received a copy of the GNU General Public License -->\n"
2048 "<!-- along with this program; if not, write to the -->\n"
2049 "<!-- Free Software Foundation, Inc., -->\n"
2050 "<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->\n"
2051 "<!-- -->\n"
2052 "<!-- Sipp default 'uas' scenario. -->\n"
2053 "<!-- -->\n"
2054 "\n"
2055 "<scenario name=\"Basic UAS responder\">\n"
2056 " <!-- By adding rrs=\"true\" (Record Route Sets), the route sets -->\n"
2057 " <!-- are saved and used for following messages sent. Useful to test -->\n"
2058 " <!-- against stateful SIP proxies/B2BUAs. -->\n"
2059 " <recv request=\"INVITE\" crlf=\"true\">\n"
2060 " </recv>\n"
2061 "\n"
2062 " <!-- The '[last_*]' keyword is replaced automatically by the -->\n"
2063 " <!-- specified header if it was present in the last message received -->\n"
2064 " <!-- (except if it was a retransmission). If the header was not -->\n"
2065 " <!-- present or if no message has been received, the '[last_*]' -->\n"
2066 " <!-- keyword is discarded, and all bytes until the end of the line -->\n"
2067 " <!-- are also discarded. -->\n"
2068 " <!-- -->\n"
2069 " <!-- If the specified header was present several times in the -->\n"
2070 " <!-- message, all occurrences are concatenated (CRLF separated) -->\n"
2071 " <!-- to be used in place of the '[last_*]' keyword. -->\n"
2072 "\n"
2073 " <send>\n"
2074 " <![CDATA[\n"
2075 "\n"
2076 " SIP/2.0 180 Ringing\n"
2077 " [last_Via:]\n"
2078 " [last_From:]\n"
2079 " [last_To:];tag=[pid]SIPpTag01[call_number]\n"
2080 " [last_Call-ID:]\n"
2081 " [last_CSeq:]\n"
2082 " Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"
2083 " Content-Length: 0\n"
2084 "\n"
2085 " ]]>\n"
2086 " </send>\n"
2087 "\n"
2088 " <send retrans=\"500\">\n"
2089 " <![CDATA[\n"
2090 "\n"
2091 " SIP/2.0 200 OK\n"
2092 " [last_Via:]\n"
2093 " [last_From:]\n"
2094 " [last_To:];tag=[pid]SIPpTag01[call_number]\n"
2095 " [last_Call-ID:]\n"
2096 " [last_CSeq:]\n"
2097 " Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"
2098 " Content-Type: application/sdp\n"
2099 " Content-Length: [len]\n"
2100 "\n"
2101 " v=0\n"
2102 " o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]\n"
2103 " s=-\n"
2104 " c=IN IP[media_ip_type] [media_ip]\n"
2105 " t=0 0\n"
2106 " m=audio [media_port] RTP/AVP 0\n"
2107 " a=rtpmap:0 PCMU/8000\n"
2108 "\n"
2109 " ]]>\n"
2110 " </send>\n"
2111 "\n"
2112 " <recv request=\"ACK\"\n"
2113 " optional=\"true\"\n"
2114 " rtd=\"true\"\n"
2115 " crlf=\"true\">\n"
2116 " </recv>\n"
2117 "\n"
2118 " <recv request=\"BYE\">\n"
2119 " </recv>\n"
2120 "\n"
2121 " <send>\n"
2122 " <![CDATA[\n"
2123 "\n"
2124 " SIP/2.0 200 OK\n"
2125 " [last_Via:]\n"
2126 " [last_From:]\n"
2127 " [last_To:]\n"
2128 " [last_Call-ID:]\n"
2129 " [last_CSeq:]\n"
2130 " Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"
2131 " Content-Length: 0\n"
2132 "\n"
2133 " ]]>\n"
2134 " </send>\n"
2135 "\n"
2136 " <!-- Keep the call open for a while in case the 200 is lost to be -->\n"
2137 " <!-- able to retransmit it if we receive the BYE again. -->\n"
2138 " <timewait milliseconds=\"4000\"/>\n"
2139 "\n"
2140 "\n"
2141 " <!-- definition of the response time repartition table (unit is ms) -->\n"
2142 " <ResponseTimeRepartition value=\"10, 20, 30, 40, 50, 100, 150, 200\"/>\n"
2143 "\n"
2144 " <!-- definition of the call length repartition table (unit is ms) -->\n"
2145 " <CallLengthRepartition value=\"10, 50, 100, 500, 1000, 5000, 10000\"/>\n"
2146 "\n"
2147 "</scenario>\n"
2148 "\n",
2149
2150 /************* Default_scenario[2] ***************/
2151 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n"
2152 "<!DOCTYPE scenario SYSTEM \"sipp.dtd\">\n"
2153 "\n"
2154 "<!-- This program is free software; you can redistribute it and/or -->\n"
2155 "<!-- modify it under the terms of the GNU General Public License as -->\n"
2156 "<!-- published by the Free Software Foundation; either version 2 of the -->\n"
2157 "<!-- License, or (at your option) any later version. -->\n"
2158 "<!-- -->\n"
2159 "<!-- This program is distributed in the hope that it will be useful, -->\n"
2160 "<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->\n"
2161 "<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->\n"
2162 "<!-- GNU General Public License for more details. -->\n"
2163 "<!-- -->\n"
2164 "<!-- You should have received a copy of the GNU General Public License -->\n"
2165 "<!-- along with this program; if not, write to the -->\n"
2166 "<!-- Free Software Foundation, Inc., -->\n"
2167 "<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->\n"
2168 "<!-- -->\n"
2169 "<!-- Sipp default 'regexp client' scenario. -->\n"
2170 "<!-- -->\n"
2171 "\n"
2172 "<scenario name=\"Client with regexp scenario\">\n"
2173 " <send retrans=\"500\">\n"
2174 " <![CDATA[\n"
2175 "\n"
2176 " INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"
2177 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
2178 " From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag02[call_number]\n"
2179 " To: [service] <sip:[service]@[remote_ip]:[remote_port]>\n"
2180 " Call-ID: [call_id]\n"
2181 " CSeq: 1 INVITE\n"
2182 " Contact: sip:sipp@[local_ip]:[local_port]\n"
2183 " Max-Forwards: 70\n"
2184 " Subject: Performance Test\n"
2185 " Content-Type: application/sdp\n"
2186 " Content-Length: [len]\n"
2187 "\n"
2188 " v=0\n"
2189 " o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]\n"
2190 " s=-\n"
2191 " c=IN IP[media_ip_type] [media_ip]\n"
2192 " t=0 0\n"
2193 " m=audio [media_port] RTP/AVP 0\n"
2194 " a=rtpmap:0 PCMU/8000\n"
2195 "\n"
2196 " ]]>\n"
2197 " </send>\n"
2198 "\n"
2199 " <recv response=\"100\"\n"
2200 " optional=\"true\">\n"
2201 " </recv>\n"
2202 "\n"
2203 " <recv response=\"180\" optional=\"true\">\n"
2204 " </recv>\n"
2205 " <recv response=\"183\" optional=\"true\">\n"
2206 " </recv>\n"
2207 "\n"
2208 " <recv response=\"200\" start_rtd=\"true\">\n"
2209 " <!-- Definition of regexp in the action tag. The regexp must follow -->\n"
2210 " <!-- the Posix Extended standard (POSIX 1003.2), see: -->\n"
2211 " <!-- -->\n"
2212 " <!-- http://www.opengroup.org/onlinepubs/007908799/xbd/re.html -->\n"
2213 " <!-- -->\n"
2214 " <!-- regexp : Contain the regexp to use for matching the -->\n"
2215 " <!-- received message -->\n"
2216 " <!-- MANDATORY -->\n"
2217 " <!-- search_in : msg (try to match against the entire message) -->\n"
2218 " <!-- : hdr (try to match against a specific SIP header -->\n"
2219 " <!-- (passed in the header tag) -->\n"
2220 " <!-- OPTIONAL - default value : msg -->\n"
2221 " <!-- header : Header to try to match against. -->\n"
2222 " <!-- Only used when the search_in tag is set to hdr -->\n"
2223 " <!-- MANDATORY IF search_in is equal to hdr -->\n"
2224 " <!-- check_it : if set to true, the call is marked as failed if -->\n"
2225 " <!-- the regexp doesn't match. -->\n"
2226 " <!-- OPTIONAL - default value : false -->\n"
2227 " <!-- assign_to : contain the variable id (integer) or a list of -->\n"
2228 " <!-- variable id which will be used to store the -->\n"
2229 " <!-- result of the matching process between the regexp -->\n"
2230 " <!-- and the message. This variable can be re-used at -->\n"
2231 " <!-- a later time in the scenario using '[$n]' syntax -->\n"
2232 " <!-- where n is the variable id. -->\n"
2233 " <!-- MANDATORY -->\n"
2234 " <action>\n"
2235 " <ereg regexp=\"[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[:][0-9]{1,5}\" \n"
2236 " search_in=\"msg\" \n"
2237 " check_it=\"true\" \n"
2238 " assign_to=\"1\"/>\n"
2239 " <ereg regexp=\".*\" \n"
2240 " search_in=\"hdr\" \n"
2241 " header=\"Contact:\" \n"
2242 " check_it=\"true\" \n"
2243 " assign_to=\"6\"/>\n"
2244 " <ereg regexp=\"o=([[:alnum:]]*) ([[:alnum:]]*) ([[:alnum:]]*)\"\n"
2245 " search_in=\"msg\" \n"
2246 " check_it=\"true\" \n"
2247 " assign_to=\"3,4,5,8\"/>\n"
2248 " </action>\n"
2249 " </recv>\n"
2250 "\n"
2251 " <send>\n"
2252 " <![CDATA[\n"
2253 " ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"
2254 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
2255 " From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag02[call_number]\n"
2256 " To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n"
2257 " Call-ID: [call_id]\n"
2258 " CSeq: 1 ACK\n"
2259 " retrievedIp: [$1]\n"
2260 " retrievedContact:[$6]\n"
2261 " retrievedSdpOrigin:[$3]\n"
2262 " retrievedSdpOrigin-username:[$4]\n"
2263 " retrievedSdpOrigin-session-id:[$5]\n"
2264 " retrievedSdpOrigin-version:[$8]\n"
2265 " Contact: sip:sipp@[local_ip]:[local_port]\n"
2266 " Max-Forwards: 70\n"
2267 " Subject: Performance Test\n"
2268 " Content-Length: 0\n"
2269 " ]]>\n"
2270 " </send>\n"
2271 "\n"
2272 " <!-- This delay can be customized by the -d command-line option -->\n"
2273 " <!-- or by adding a 'milliseconds = \"value\"' option here. -->\n"
2274 " <pause milliseconds = \"1000\"/>\n"
2275 "\n"
2276 " <!-- The 'crlf' option inserts a blank line in the statistics report. -->\n"
2277 " <send retrans=\"500\">\n"
2278 " <![CDATA[\n"
2279 "\n"
2280 " BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"
2281 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
2282 " From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag02[call_number]\n"
2283 " To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n"
2284 " Call-ID: [call_id]\n"
2285 " CSeq: 2 BYE\n"
2286 " Contact: sip:sipp@[local_ip]:[local_port]\n"
2287 " Max-Forwards: 70\n"
2288 " Subject: Performance Test\n"
2289 " Content-Length: 0\n"
2290 "\n"
2291 " ]]>\n"
2292 " </send>\n"
2293 "\n"
2294 " <recv response=\"200\" crlf=\"true\" rtd=\"true\">\n"
2295 " </recv>\n"
2296 "\n"
2297 " <!-- definition of the response time repartition table (unit is ms) -->\n"
2298 " <ResponseTimeRepartition value=\"1000, 1040, 1080, 1120, 1160, 1200\"/>\n"
2299 "\n"
2300 " <!-- definition of the call length repartition table (unit is ms) -->\n"
2301 " <CallLengthRepartition value=\"1000, 1100, 1200, 1300, 1400\"/>\n"
2302 "\n"
2303 "</scenario>\n"
2304 "\n",
2305
2306 /************* Default_scenario[3] ***************/
2307 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n"
2308 "<!DOCTYPE scenario SYSTEM \"sipp.dtd\">\n"
2309 "\n"
2310 "<!-- This program is free software; you can redistribute it and/or -->\n"
2311 "<!-- modify it under the terms of the GNU General Public License as -->\n"
2312 "<!-- published by the Free Software Foundation; either version 2 of the -->\n"
2313 "<!-- License, or (at your option) any later version. -->\n"
2314 "<!-- -->\n"
2315 "<!-- This program is distributed in the hope that it will be useful, -->\n"
2316 "<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->\n"
2317 "<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->\n"
2318 "<!-- GNU General Public License for more details. -->\n"
2319 "<!-- -->\n"
2320 "<!-- You should have received a copy of the GNU General Public License -->\n"
2321 "<!-- along with this program; if not, write to the -->\n"
2322 "<!-- Free Software Foundation, Inc., -->\n"
2323 "<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->\n"
2324 "<!-- -->\n"
2325 "<!-- 3PCC - Controller - A side -->\n"
2326 "<!-- -->\n"
2327 "<!-- A Controller B -->\n"
2328 "<!-- |(1) INVITE no SDP | | -->\n"
2329 "<!-- |<==================| | -->\n"
2330 "<!-- |(2) 200 offer1 | | -->\n"
2331 "<!-- |==================>| | -->\n"
2332 "<!-- | |(3) INVITE offer1 | -->\n"
2333 "<!-- | |==================>| -->\n"
2334 "<!-- | |(4) 200 OK answer1 | -->\n"
2335 "<!-- | |<==================| -->\n"
2336 "<!-- | |(5) ACK | -->\n"
2337 "<!-- | |==================>| -->\n"
2338 "<!-- |(6) ACK answer1 | | -->\n"
2339 "<!-- |<==================| | -->\n"
2340 "<!-- |(7) RTP | | -->\n"
2341 "<!-- |.......................................| -->\n"
2342 "<!-- -->\n"
2343 "\n"
2344 "<scenario name=\"3PCC Controller - A side\">\n"
2345 " <send retrans=\"500\">\n"
2346 " <![CDATA[\n"
2347 "\n"
2348 " INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"
2349 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
2350 " From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag03[call_number]\n"
2351 " To: [service] <sip:[service]@[remote_ip]:[remote_port]>\n"
2352 " Call-ID: [call_id]\n"
2353 " CSeq: 1 INVITE\n"
2354 " Contact: sip:sipp@[local_ip]:[local_port]\n"
2355 " Max-Forwards: 70\n"
2356 " Subject: Performance Test\n"
2357 " Content-Length: 0\n"
2358 "\n"
2359 " ]]>\n"
2360 " </send>\n"
2361 "\n"
2362 " <recv response=\"100\" optional=\"true\"> </recv>\n"
2363 " <recv response=\"180\" optional=\"true\"> </recv>\n"
2364 " <recv response=\"183\" optional=\"true\"> </recv>\n"
2365 " <recv response=\"200\" crlf=\"true\" start_rtd=\"true\">\n"
2366 " <action>\n"
2367 " <ereg regexp=\"Content-Type:.*\" \n"
2368 " search_in=\"msg\" \n"
2369 " assign_to=\"1\" /> \n"
2370 " </action>\n"
2371 " </recv>\n"
2372 "\n"
2373 " <sendCmd>\n"
2374 " <![CDATA[\n"
2375 " Call-ID: [call_id]\n"
2376 " [$1]\n"
2377 "\n"
2378 " ]]>\n"
2379 " </sendCmd>\n"
2380 " \n"
2381 " <recvCmd>\n"
2382 " <action>\n"
2383 " <ereg regexp=\"Content-Type:.*\" \n"
2384 " search_in=\"msg\" \n"
2385 " assign_to=\"2\" /> \n"
2386 " </action>\n"
2387 " \n"
2388 " </recvCmd>\n"
2389 " \n"
2390 " <send rtd=\"true\">\n"
2391 " <![CDATA[\n"
2392 "\n"
2393 " ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"
2394 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
2395 " From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag03[call_number]\n"
2396 " To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n"
2397 " Call-ID: [call_id]\n"
2398 " CSeq: 1 ACK\n"
2399 " Contact: sip:sipp@[local_ip]:[local_port]\n"
2400 " Max-Forwards: 70\n"
2401 " Subject: Performance Test\n"
2402 " [$2]\n"
2403 "\n"
2404 " ]]>\n"
2405 " </send>\n"
2406 "\n"
2407 " <pause milliseconds=\"1000\"/>\n"
2408 "\n"
2409 " <!-- The 'crlf' option inserts a blank line in the statistics report. -->\n"
2410 " <send retrans=\"500\">\n"
2411 " <![CDATA[\n"
2412 "\n"
2413 " BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"
2414 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
2415 " From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag03[call_number]\n"
2416 " To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n"
2417 " Call-ID: [call_id]\n"
2418 " CSeq: 2 BYE\n"
2419 " Contact: sip:sipp@[local_ip]:[local_port]\n"
2420 " Max-Forwards: 70\n"
2421 " Subject: Performance Test\n"
2422 " Content-Length: 0\n"
2423 "\n"
2424 " ]]>\n"
2425 " </send>\n"
2426 "\n"
2427 " <recv response=\"200\" crlf=\"true\"> </recv>\n"
2428 "\n"
2429 "</scenario>\n"
2430 "\n",
2431
2432 /************* Default_scenario[4] ***************/
2433 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n"
2434 "<!DOCTYPE scenario SYSTEM \"sipp.dtd\">\n"
2435 "\n"
2436 "<!-- This program is free software; you can redistribute it and/or -->\n"
2437 "<!-- modify it under the terms of the GNU General Public License as -->\n"
2438 "<!-- published by the Free Software Foundation; either version 2 of the -->\n"
2439 "<!-- License, or (at your option) any later version. -->\n"
2440 "<!-- -->\n"
2441 "<!-- This program is distributed in the hope that it will be useful, -->\n"
2442 "<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->\n"
2443 "<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->\n"
2444 "<!-- GNU General Public License for more details. -->\n"
2445 "<!-- -->\n"
2446 "<!-- You should have received a copy of the GNU General Public License -->\n"
2447 "<!-- along with this program; if not, write to the -->\n"
2448 "<!-- Free Software Foundation, Inc., -->\n"
2449 "<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->\n"
2450 "<!-- -->\n"
2451 "<!-- 3PCC - Controller - B side -->\n"
2452 "<!-- -->\n"
2453 "<!-- A Controller B -->\n"
2454 "<!-- |(1) INVITE no SDP | | -->\n"
2455 "<!-- |<==================| | -->\n"
2456 "<!-- |(2) 200 offer1 | | -->\n"
2457 "<!-- |==================>| | -->\n"
2458 "<!-- | |(3) INVITE offer1 | -->\n"
2459 "<!-- | |==================>| -->\n"
2460 "<!-- | |(4) 200 OK answer1 | -->\n"
2461 "<!-- | |<==================| -->\n"
2462 "<!-- | |(5) ACK | -->\n"
2463 "<!-- | |==================>| -->\n"
2464 "<!-- |(6) ACK answer1 | | -->\n"
2465 "<!-- |<==================| | -->\n"
2466 "<!-- |(7) RTP | | -->\n"
2467 "<!-- |.......................................| -->\n"
2468 "<!-- -->\n"
2469 "\n"
2470 "\n"
2471 "<scenario name=\"3PCC Controller - B side\">\n"
2472 "\n"
2473 "<recvCmd>\n"
2474 " <action>\n"
2475 " <ereg regexp=\"Content-Type:.*\" \n"
2476 " search_in=\"msg\" \n"
2477 " assign_to=\"1\" /> \n"
2478 " </action>\n"
2479 "</recvCmd>\n"
2480 "\n"
2481 " <send retrans=\"500\">\n"
2482 " <![CDATA[\n"
2483 "\n"
2484 " INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"
2485 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
2486 " From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag04[call_number]\n"
2487 " To: [service] <sip:[service]@[remote_ip]:[remote_port]>\n"
2488 " Call-ID: [call_id]\n"
2489 " CSeq: 1 INVITE\n"
2490 " Contact: sip:sipp@[local_ip]:[local_port]\n"
2491 " Max-Forwards: 70\n"
2492 " Subject: Performance Test\n"
2493 " [$1]\n"
2494 "\n"
2495 " ]]>\n"
2496 " </send>\n"
2497 "\n"
2498 " <recv response=\"100\" optional=\"true\"> </recv>\n"
2499 " <recv response=\"180\" optional=\"true\"> </recv>\n"
2500 " <recv response=\"183\" optional=\"true\"> </recv>\n"
2501 " <recv response=\"200\" crlf=\"true\">\n"
2502 " <action>\n"
2503 " <ereg regexp=\"Content-Type:.*\" \n"
2504 " search_in=\"msg\" \n"
2505 " assign_to=\"2\" /> \n"
2506 " </action>\n"
2507 " </recv>\n"
2508 " \n"
2509 " \n"
2510 " <send start_rtd=\"true\">\n"
2511 " <![CDATA[\n"
2512 "\n"
2513 " ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"
2514 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
2515 " From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag04[call_number]\n"
2516 " To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n"
2517 " Call-ID: [call_id]\n"
2518 " CSeq: 1 ACK\n"
2519 " Contact: sip:sipp@[local_ip]:[local_port]\n"
2520 " Max-Forwards: 70\n"
2521 " Subject: Performance Test\n"
2522 " Content-Length: 0\n"
2523 "\n"
2524 " ]]>\n"
2525 " </send>\n"
2526 "\n"
2527 " <sendCmd>\n"
2528 " <![CDATA[\n"
2529 " Call-ID: [call_id]\n"
2530 " [$2]\n"
2531 "\n"
2532 " ]]>\n"
2533 " </sendCmd>\n"
2534 " \n"
2535 " <pause milliseconds=\"1000\"/>\n"
2536 "\n"
2537 "\n"
2538 " <!-- The 'crlf' option inserts a blank line in the statistics report. -->\n"
2539 " <send retrans=\"500\" rtd=\"true\">\n"
2540 " <![CDATA[\n"
2541 "\n"
2542 " BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"
2543 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
2544 " From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag04[call_number]\n"
2545 " To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n"
2546 " Call-ID: [call_id]\n"
2547 " CSeq: 2 BYE\n"
2548 " Contact: sip:sipp@[local_ip]:[local_port]\n"
2549 " Max-Forwards: 70\n"
2550 " Subject: Performance Test\n"
2551 " Content-Length: 0\n"
2552 "\n"
2553 " ]]>\n"
2554 " </send>\n"
2555 "\n"
2556 " <recv response=\"200\" crlf=\"true\">\n"
2557 " </recv>\n"
2558 "\n"
2559 "\n"
2560 "</scenario>\n"
2561 "\n",
2562
2563 /************* Default_scenario[5] ***************/
2564 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n"
2565 "<!DOCTYPE scenario SYSTEM \"sipp.dtd\">\n"
2566 "\n"
2567 "<!-- This program is free software; you can redistribute it and/or -->\n"
2568 "<!-- modify it under the terms of the GNU General Public License as -->\n"
2569 "<!-- published by the Free Software Foundation; either version 2 of the -->\n"
2570 "<!-- License, or (at your option) any later version. -->\n"
2571 "<!-- -->\n"
2572 "<!-- This program is distributed in the hope that it will be useful, -->\n"
2573 "<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->\n"
2574 "<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->\n"
2575 "<!-- GNU General Public License for more details. -->\n"
2576 "<!-- -->\n"
2577 "<!-- You should have received a copy of the GNU General Public License -->\n"
2578 "<!-- along with this program; if not, write to the -->\n"
2579 "<!-- Free Software Foundation, Inc., -->\n"
2580 "<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->\n"
2581 "<!-- -->\n"
2582 "<!-- 3PCC - A side emulator -->\n"
2583 "<!-- -->\n"
2584 "<!-- A Controller B -->\n"
2585 "<!-- |(1) INVITE no SDP | | -->\n"
2586 "<!-- |<==================| | -->\n"
2587 "<!-- |(2) 200 offer1 | | -->\n"
2588 "<!-- |==================>| | -->\n"
2589 "<!-- | |(3) INVITE offer1 | -->\n"
2590 "<!-- | |==================>| -->\n"
2591 "<!-- | |(4) 200 OK answer1 | -->\n"
2592 "<!-- | |<==================| -->\n"
2593 "<!-- | |(5) ACK | -->\n"
2594 "<!-- | |==================>| -->\n"
2595 "<!-- |(6) ACK answer1 | | -->\n"
2596 "<!-- |<==================| | -->\n"
2597 "<!-- |(7) RTP | | -->\n"
2598 "<!-- |.......................................| -->\n"
2599 "<!-- -->\n"
2600 "\n"
2601 "\n"
2602 "<scenario name=\"3PCC A side\">\n"
2603 " <recv request=\"INVITE\" crlf=\"true\">\n"
2604 " </recv>\n"
2605 "\n"
2606 " <send>\n"
2607 " <![CDATA[\n"
2608 "\n"
2609 " SIP/2.0 200 OK\n"
2610 " [last_Via:]\n"
2611 " [last_From:]\n"
2612 " [last_To:];tag=[pid]SIPpTag05[call_number]\n"
2613 " [last_Call-ID:]\n"
2614 " [last_CSeq:]\n"
2615 " Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"
2616 " Content-Type: application/sdp\n"
2617 " Content-Length: [len]\n"
2618 "\n"
2619 " v=0\n"
2620 " o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]\n"
2621 " s=-\n"
2622 " c=IN IP[media_ip_type] [media_ip]\n"
2623 " t=0 0\n"
2624 " m=audio [media_port] RTP/AVP 0\n"
2625 " a=rtpmap:0 PCMU/8000\n"
2626 "\n"
2627 " ]]>\n"
2628 " </send>\n"
2629 "\n"
2630 " <recv request=\"ACK\" rtd=\"true\" crlf=\"true\"> </recv>\n"
2631 "\n"
2632 " <!-- RTP flow starts from here! -->\n"
2633 "\n"
2634 " <recv request=\"BYE\" crlf=\"true\"> </recv>\n"
2635 "\n"
2636 " <send>\n"
2637 " <![CDATA[\n"
2638 "\n"
2639 " SIP/2.0 200 OK\n"
2640 " [last_Via:]\n"
2641 " [last_From:]\n"
2642 " [last_To:]\n"
2643 " [last_Call-ID:]\n"
2644 " [last_CSeq:]\n"
2645 " Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"
2646 " Content-Length: 0\n"
2647 "\n"
2648 " ]]>\n"
2649 " </send>\n"
2650 "\n"
2651 " <!-- Keep the call open for a while in case the 200 is lost to be -->\n"
2652 " <!-- able to retransmit it if we receive the BYE again. -->\n"
2653 " <timewait milliseconds=\"2000\"/>\n"
2654 "\n"
2655 "</scenario>\n"
2656 "\n",
2657
2658 /************* Default_scenario[6] ***************/
2659 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n"
2660 "<!DOCTYPE scenario SYSTEM \"sipp.dtd\">\n"
2661 "\n"
2662 "<!-- This program is free software; you can redistribute it and/or -->\n"
2663 "<!-- modify it under the terms of the GNU General Public License as -->\n"
2664 "<!-- published by the Free Software Foundation; either version 2 of the -->\n"
2665 "<!-- License, or (at your option) any later version. -->\n"
2666 "<!-- -->\n"
2667 "<!-- This program is distributed in the hope that it will be useful, -->\n"
2668 "<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->\n"
2669 "<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->\n"
2670 "<!-- GNU General Public License for more details. -->\n"
2671 "<!-- -->\n"
2672 "<!-- You should have received a copy of the GNU General Public License -->\n"
2673 "<!-- along with this program; if not, write to the -->\n"
2674 "<!-- Free Software Foundation, Inc., -->\n"
2675 "<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->\n"
2676 "<!-- -->\n"
2677 "<!-- 3PCC - B side emulator -->\n"
2678 "<!-- -->\n"
2679 "<!-- A Controller B -->\n"
2680 "<!-- |(1) INVITE no SDP | | -->\n"
2681 "<!-- |<==================| | -->\n"
2682 "<!-- |(2) 200 offer1 | | -->\n"
2683 "<!-- |==================>| | -->\n"
2684 "<!-- | |(3) INVITE offer1 | -->\n"
2685 "<!-- | |==================>| -->\n"
2686 "<!-- | |(4) 200 OK answer1 | -->\n"
2687 "<!-- | |<==================| -->\n"
2688 "<!-- | |(5) ACK | -->\n"
2689 "<!-- | |==================>| -->\n"
2690 "<!-- |(6) ACK answer1 | | -->\n"
2691 "<!-- |<==================| | -->\n"
2692 "<!-- |(7) RTP | | -->\n"
2693 "<!-- |.......................................| -->\n"
2694 "<!-- -->\n"
2695 "\n"
2696 "\n"
2697 "\n"
2698 "<scenario name=\"3PCC B side\">\n"
2699 " <recv request=\"INVITE\" crlf=\"true\"> </recv>\n"
2700 "\n"
2701 " <send>\n"
2702 " <![CDATA[\n"
2703 "\n"
2704 " SIP/2.0 200 OK\n"
2705 " [last_Via:]\n"
2706 " [last_From:]\n"
2707 " [last_To:];tag=[pid]SIPpTag06[call_number]\n"
2708 " [last_Call-ID:]\n"
2709 " [last_CSeq:]\n"
2710 " Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"
2711 " Content-Type: application/sdp\n"
2712 " Content-Length: [len]\n"
2713 "\n"
2714 " v=0\n"
2715 " o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]\n"
2716 " s=-\n"
2717 " c=IN IP[media_ip_type] [media_ip]\n"
2718 " t=0 0\n"
2719 " m=audio [media_port] RTP/AVP 0\n"
2720 " a=rtpmap:0 PCMU/8000\n"
2721 "\n"
2722 " ]]>\n"
2723 " </send>\n"
2724 "\n"
2725 " <recv request=\"ACK\" rtd=\"true\" crlf=\"true\"> </recv>\n"
2726 "\n"
2727 " <!-- RTP flow starts from here! -->\n"
2728 "\n"
2729 " <recv request=\"BYE\"> </recv>\n"
2730 "\n"
2731 " <send>\n"
2732 " <![CDATA[\n"
2733 "\n"
2734 " SIP/2.0 200 OK\n"
2735 " [last_Via:]\n"
2736 " [last_From:]\n"
2737 " [last_To:]\n"
2738 " [last_Call-ID:]\n"
2739 " [last_CSeq:]\n"
2740 " Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"
2741 " Content-Length: 0\n"
2742 "\n"
2743 " ]]>\n"
2744 " </send>\n"
2745 "\n"
2746 " <!-- Keep the call open for a while in case the 200 is lost to be -->\n"
2747 " <!-- able to retransmit it if we receive the BYE again. -->\n"
2748 " <timewait milliseconds=\"2000\"/>\n"
2749 "\n"
2750 "</scenario>\n",
2751
2752 /************* Default_scenario[7] ***************/
2753 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n"
2754 "<!DOCTYPE scenario SYSTEM \"sipp.dtd\">\n"
2755 "\n"
2756 "<!-- This program is free software; you can redistribute it and/or -->\n"
2757 "<!-- modify it under the terms of the GNU General Public License as -->\n"
2758 "<!-- published by the Free Software Foundation; either version 2 of the -->\n"
2759 "<!-- License, or (at your option) any later version. -->\n"
2760 "<!-- -->\n"
2761 "<!-- This program is distributed in the hope that it will be useful, -->\n"
2762 "<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->\n"
2763 "<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->\n"
2764 "<!-- GNU General Public License for more details. -->\n"
2765 "<!-- -->\n"
2766 "<!-- You should have received a copy of the GNU General Public License -->\n"
2767 "<!-- along with this program; if not, write to the -->\n"
2768 "<!-- Free Software Foundation, Inc., -->\n"
2769 "<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->\n"
2770 "<!-- -->\n"
2771 "<!-- Sipp default 'branchc' scenario. -->\n"
2772 "<!-- -->\n"
2773 "\n"
2774 "<scenario name=\"branch_client\">\n"
2775 " <send retrans=\"500\">\n"
2776 " <![CDATA[\n"
2777 "\n"
2778 " REGISTER sip:CA.cym.com SIP/2.0\n"
2779 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
2780 " From: ua1 <sip:ua1@nnl.cym:[local_port]>;tag=[pid]SIPpTag07[call_number]\n"
2781 " To: ua1 <sip:ua1@nnl.cym:[local_port]>\n"
2782 " Call-ID: [call_id]\n"
2783 " CSeq: 1 REGISTER\n"
2784 " Contact: sip:ua1@[local_ip]:[local_port]\n"
2785 " Content-Length: 0\n"
2786 " Expires: 300\n"
2787 "\n"
2788 " ]]>\n"
2789 " </send>\n"
2790 "\n"
2791 " <!-- simple case - just jump over a line -->\n"
2792 " <recv response=\"200\" rtd=\"true\" next=\"5\">\n"
2793 " </recv>\n"
2794 "\n"
2795 " <recv response=\"200\">\n"
2796 " </recv>\n"
2797 "\n"
2798 " <label id=\"5\"/>\n"
2799 "\n"
2800 " <send retrans=\"500\">\n"
2801 " <![CDATA[\n"
2802 "\n"
2803 " INVITE sip:ua2@CA.cym.com SIP/2.0\n"
2804 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
2805 " From: ua[call_number] <sip:ua1@nnl.cym:[local_port]>;tag=[pid]SIPpTag07b[call_number]\n"
2806 " To: ua2 <sip:ua2@nnl.cym:[remote_port]>\n"
2807 " Call-ID: [call_id]\n"
2808 " CSeq: 1 INVITE\n"
2809 " Contact: sip:ua1@[local_ip]:[local_port]\n"
2810 " Max-Forwards: 70\n"
2811 " Subject: Performance Test\n"
2812 " Content-Type: application/sdp\n"
2813 " Content-Length: [len]\n"
2814 "\n"
2815 " v=0\n"
2816 " o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]\n"
2817 " s=-\n"
2818 " c=IN IP[media_ip_type] [media_ip]\n"
2819 " t=0 0\n"
2820 " m=audio [media_port] RTP/AVP 0\n"
2821 " a=rtpmap:0 PCMU/8000\n"
2822 "\n"
2823 " ]]>\n"
2824 " </send>\n"
2825 "\n"
2826 " <recv response=\"100\" optional=\"true\">\n"
2827 " </recv>\n"
2828 "\n"
2829 " <recv response=\"180\" optional=\"true\">\n"
2830 " </recv>\n"
2831 "\n"
2832 " <recv response=\"183\" optional=\"true\">\n"
2833 " </recv>\n"
2834 "\n"
2835 " <!-- Do something different on an optional receive -->\n"
2836 " <recv response=\"403\" optional=\"true\" next=\"1\">\n"
2837 " </recv>\n"
2838 "\n"
2839 " <recv response=\"200\">\n"
2840 " <action>\n"
2841 " <ereg regexp=\"ua25\"\n"
2842 " search_in=\"hdr\"\n"
2843 " header=\"From: \"\n"
2844 " assign_to=\"8\"/>\n"
2845 " </action>\n"
2846 " </recv>\n"
2847 "\n"
2848 " <!-- set variable 8 above on 25th call, send the ACK but skip the pause for it -->\n"
2849 " <send next=\"1\" test=\"8\">\n"
2850 " <![CDATA[\n"
2851 "\n"
2852 " ACK sip:ua2@CA.cym.com SIP/2.0\n"
2853 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
2854 " From: ua1 <sip:ua1@nnl.cym:[local_port]>;tag=[pid]SIPpTag07b[call_number]\n"
2855 " To: ua2 <sip:ua2@nnl.cym:[remote_port]>[peer_tag_param]\n"
2856 " Call-ID: [call_id]\n"
2857 " CSeq: 1 ACK\n"
2858 " Contact: sip:ua1@[local_ip]:[local_port]\n"
2859 " Max-Forwards: 70\n"
2860 " Subject: Performance Test\n"
2861 " Content-Length: 0\n"
2862 "\n"
2863 " ]]>\n"
2864 " </send>\n"
2865 "\n"
2866 " <pause milliseconds=\"5000\"/>\n"
2867 "\n"
2868 " <label id=\"1\"/>\n"
2869 "\n"
2870 " <send retrans=\"500\">\n"
2871 " <![CDATA[\n"
2872 "\n"
2873 " BYE sip:ua2@CA.cym.com SIP/2.0\n"
2874 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
2875 " From: ua1 <sip:ua1@nnl.cym:[local_port]>;tag=[pid]SIPpTag07b[call_number]\n"
2876 " To: ua2 <sip:ua2@nnl.cym:[remote_port]>[peer_tag_param]\n"
2877 " Call-ID: [call_id]\n"
2878 " CSeq: 2 BYE\n"
2879 " Contact: sip:ua1@[local_ip]:[local_port]\n"
2880 " Max-Forwards: 70\n"
2881 " Subject: Performance Test\n"
2882 " Content-Length: 0\n"
2883 "\n"
2884 " ]]>\n"
2885 " </send>\n"
2886 "\n"
2887 " <recv response=\"200\" crlf=\"true\">\n"
2888 " </recv>\n"
2889 "\n"
2890 " <pause milliseconds=\"4000\"/>\n"
2891 "\n"
2892 " <!-- definition of the response time repartition table (unit is ms) -->\n"
2893 " <ResponseTimeRepartition value=\"10, 20, 30, 40, 50, 100, 150, 200\"/>\n"
2894 "\n"
2895 " <!-- definition of the call length repartition table (unit is ms) -->\n"
2896 " <CallLengthRepartition value=\"10, 50, 100, 500, 1000, 5000, 10000\"/>\n"
2897 "\n"
2898 "</scenario>\n"
2899 "\n",
2900
2901 /************* Default_scenario[8] ***************/
2902 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n"
2903 "<!DOCTYPE scenario SYSTEM \"sipp.dtd\">\n"
2904 "\n"
2905 "<!-- This program is free software; you can redistribute it and/or -->\n"
2906 "<!-- modify it under the terms of the GNU General Public License as -->\n"
2907 "<!-- published by the Free Software Foundation; either version 2 of the -->\n"
2908 "<!-- License, or (at your option) any later version. -->\n"
2909 "<!-- -->\n"
2910 "<!-- This program is distributed in the hope that it will be useful, -->\n"
2911 "<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->\n"
2912 "<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->\n"
2913 "<!-- GNU General Public License for more details. -->\n"
2914 "<!-- -->\n"
2915 "<!-- You should have received a copy of the GNU General Public License -->\n"
2916 "<!-- along with this program; if not, write to the -->\n"
2917 "<!-- Free Software Foundation, Inc., -->\n"
2918 "<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->\n"
2919 "<!-- -->\n"
2920 "<!-- Sipp default 'branchs' scenario. -->\n"
2921 "<!-- -->\n"
2922 "\n"
2923 "<scenario name=\"branch_server\">\n"
2924 " <recv request=\"REGISTER\">\n"
2925 " </recv>\n"
2926 "\n"
2927 " <send>\n"
2928 " <![CDATA[\n"
2929 "\n"
2930 " SIP/2.0 200 OK\n"
2931 " [last_Via:]\n"
2932 " [last_From:]\n"
2933 " [last_To:];tag=[pid]SIPpTag08[call_number]\n"
2934 " [last_Call-ID:]\n"
2935 " [last_CSeq:]\n"
2936 " Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"
2937 " Content-Length: 0\n"
2938 " Expires: 300\n"
2939 "\n"
2940 " ]]>\n"
2941 " </send>\n"
2942 "\n"
2943 " <!-- Set variable 3 if the ua is of the form ua2... -->\n"
2944 " <recv request=\"INVITE\" crlf=\"true\">\n"
2945 " <action>\n"
2946 " <ereg regexp=\"ua2\"\n"
2947 " search_in=\"hdr\"\n"
2948 " header=\"From: \"\n"
2949 " assign_to=\"3\"/>\n"
2950 " </action>\n"
2951 " </recv>\n"
2952 "\n"
2953 " <!-- send 180 then trying if variable 3 is set -->\n"
2954 " <send next=\"1\" test=\"3\">\n"
2955 " <![CDATA[\n"
2956 "\n"
2957 " SIP/2.0 180 Ringing\n"
2958 " [last_Via:]\n"
2959 " [last_From:]\n"
2960 " [last_To:];tag=[pid]SIPpTag08b[call_number]\n"
2961 " [last_Call-ID:]\n"
2962 " [last_CSeq:]\n"
2963 " Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"
2964 " Content-Length: 0\n"
2965 "\n"
2966 " ]]>\n"
2967 " </send>\n"
2968 "\n"
2969 " <!-- if not, send a 403 error then skip to wait for a BYE -->\n"
2970 " <send next=\"2\">\n"
2971 " <![CDATA[\n"
2972 "\n"
2973 " SIP/2.0 403 Error\n"
2974 " [last_Via:]\n"
2975 " [last_From:]\n"
2976 " [last_To:];tag=[pid]SIPpTag08b[call_number]\n"
2977 " [last_Call-ID:]\n"
2978 " [last_CSeq:]\n"
2979 " Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"
2980 " Content-Length: 0\n"
2981 "\n"
2982 " ]]>\n"
2983 " </send>\n"
2984 "\n"
2985 " <label id=\"1\"/>\n"
2986 "\n"
2987 " <send>\n"
2988 " <![CDATA[\n"
2989 "\n"
2990 " SIP/2.0 100 Trying\n"
2991 " [last_Via:]\n"
2992 " [last_From:]\n"
2993 " [last_To:];tag=[pid]SIPpTag08b[call_number]\n"
2994 " [last_Call-ID:]\n"
2995 " [last_CSeq:]\n"
2996 " Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"
2997 " Content-Length: 0\n"
2998 "\n"
2999 " ]]>\n"
3000 " </send>\n"
3001 "\n"
3002 " <send retrans=\"500\">\n"
3003 " <![CDATA[\n"
3004 "\n"
3005 " SIP/2.0 200 OK\n"
3006 " [last_Via:]\n"
3007 " [last_From:]\n"
3008 " [last_To:];tag=[pid]SIPpTag08b[call_number]\n"
3009 " [last_Call-ID:]\n"
3010 " [last_CSeq:]\n"
3011 " Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"
3012 " Content-Type: application/sdp\n"
3013 " Content-Length: [len]\n"
3014 "\n"
3015 " v=0\n"
3016 " o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]\n"
3017 " s=-\n"
3018 " c=IN IP[media_ip_type] [media_ip]\n"
3019 " t=0 0\n"
3020 " m=audio [media_port] RTP/AVP 0\n"
3021 " a=rtpmap:0 PCMU/8000\n"
3022 "\n"
3023 " ]]>\n"
3024 " </send>\n"
3025 "\n"
3026 " <recv request=\"ACK\"\n"
3027 " optional=\"true\"\n"
3028 " rtd=\"true\"\n"
3029 " crlf=\"true\">\n"
3030 " </recv>\n"
3031 "\n"
3032 " <label id=\"2\"/>\n"
3033 "\n"
3034 " <recv request=\"BYE\">\n"
3035 " </recv>\n"
3036 "\n"
3037 " <send>\n"
3038 " <![CDATA[\n"
3039 "\n"
3040 " SIP/2.0 200 OK\n"
3041 " [last_Via:]\n"
3042 " [last_From:]\n"
3043 " [last_To:]\n"
3044 " [last_Call-ID:]\n"
3045 " [last_CSeq:]\n"
3046 " Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"
3047 " Content-Length: 0\n"
3048 "\n"
3049 " ]]>\n"
3050 " </send>\n"
3051 "\n"
3052 " <!-- Keep the call open for a while in case the 200 is lost to be -->\n"
3053 " <!-- able to retransmit it if we receive the BYE again. -->\n"
3054 " <timewait milliseconds=\"4000\"/>\n"
3055 "\n"
3056 " <!-- Definition of the response time repartition table (unit is ms) -->\n"
3057 " <ResponseTimeRepartition value=\"10, 20, 30, 40, 50, 100, 150, 200\"/>\n"
3058 "\n"
3059 " <!-- Definition of the call length repartition table (unit is ms) -->\n"
3060 " <CallLengthRepartition value=\"10, 50, 100, 500, 1000, 5000, 10000\"/>\n"
3061 "\n"
3062 "</scenario>\n"
3063 "\n",
3064
3065 /* Although this scenario will not work without pcap play enabled, there is no
3066 * harm in including it in the binary anyway, because the user could have
3067 * dumped it and passed it with -sf. */
3068
3069 /************* Default_scenario[9] ***************/
3070 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n"
3071 "<!DOCTYPE scenario SYSTEM \"sipp.dtd\">\n"
3072 "\n"
3073 "<!-- This program is free software; you can redistribute it and/or -->\n"
3074 "<!-- modify it under the terms of the GNU General Public License as -->\n"
3075 "<!-- published by the Free Software Foundation; either version 2 of the -->\n"
3076 "<!-- License, or (at your option) any later version. -->\n"
3077 "<!-- -->\n"
3078 "<!-- This program is distributed in the hope that it will be useful, -->\n"
3079 "<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->\n"
3080 "<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->\n"
3081 "<!-- GNU General Public License for more details. -->\n"
3082 "<!-- -->\n"
3083 "<!-- You should have received a copy of the GNU General Public License -->\n"
3084 "<!-- along with this program; if not, write to the -->\n"
3085 "<!-- Free Software Foundation, Inc., -->\n"
3086 "<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->\n"
3087 "<!-- -->\n"
3088 "<!-- Sipp 'uac' scenario with pcap (rtp) play -->\n"
3089 "<!-- -->\n"
3090 "\n"
3091 "<scenario name=\"UAC with media\">\n"
3092 " <!-- In client mode (sipp placing calls), the Call-ID MUST be -->\n"
3093 " <!-- generated by sipp. To do so, use [call_id] keyword. -->\n"
3094 " <send retrans=\"500\">\n"
3095 " <![CDATA[\n"
3096 "\n"
3097 " INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"
3098 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
3099 " From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag09[call_number]\n"
3100 " To: [service] <sip:[service]@[remote_ip]:[remote_port]>\n"
3101 " Call-ID: [call_id]\n"
3102 " CSeq: 1 INVITE\n"
3103 " Contact: sip:sipp@[local_ip]:[local_port]\n"
3104 " Max-Forwards: 70\n"
3105 " Subject: Performance Test\n"
3106 " Content-Type: application/sdp\n"
3107 " Content-Length: [len]\n"
3108 "\n"
3109 " v=0\n"
3110 " o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]\n"
3111 " s=-\n"
3112 " c=IN IP[local_ip_type] [local_ip]\n"
3113 " t=0 0\n"
3114 " m=audio [auto_media_port] RTP/AVP 8 101\n"
3115 " a=rtpmap:8 PCMA/8000\n"
3116 " a=rtpmap:101 telephone-event/8000\n"
3117 " a=fmtp:101 0-11,16\n"
3118 "\n"
3119 " ]]>\n"
3120 " </send>\n"
3121 "\n"
3122 " <recv response=\"100\" optional=\"true\">\n"
3123 " </recv>\n"
3124 "\n"
3125 " <recv response=\"180\" optional=\"true\">\n"
3126 " </recv>\n"
3127 "\n"
3128 " <!-- By adding rrs=\"true\" (Record Route Sets), the route sets -->\n"
3129 " <!-- are saved and used for following messages sent. Useful to test -->\n"
3130 " <!-- against stateful SIP proxies/B2BUAs. -->\n"
3131 " <recv response=\"200\" rtd=\"true\" crlf=\"true\">\n"
3132 " </recv>\n"
3133 "\n"
3134 " <!-- Packet lost can be simulated in any send/recv message by -->\n"
3135 " <!-- by adding the 'lost = \"10\"'. Value can be [1-100] percent. -->\n"
3136 " <send>\n"
3137 " <![CDATA[\n"
3138 "\n"
3139 " ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"
3140 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
3141 " From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag09[call_number]\n"
3142 " To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n"
3143 " Call-ID: [call_id]\n"
3144 " CSeq: 1 ACK\n"
3145 " Contact: sip:sipp@[local_ip]:[local_port]\n"
3146 " Max-Forwards: 70\n"
3147 " Subject: Performance Test\n"
3148 " Content-Length: 0\n"
3149 "\n"
3150 " ]]>\n"
3151 " </send>\n"
3152 "\n"
3153 " <!-- Play a pre-recorded PCAP file (RTP stream) -->\n"
3154 " <nop>\n"
3155 " <action>\n"
3156 " <exec play_pcap_audio=\"/usr/local/share/sipp/pcap/g711a.pcap\"/>\n"
3157 " </action>\n"
3158 " </nop>\n"
3159 "\n"
3160 " <!-- Pause 8 seconds, which is approximately the duration of the -->\n"
3161 " <!-- PCAP file -->\n"
3162 " <pause milliseconds=\"8000\"/>\n"
3163 "\n"
3164 " <!-- Play an out of band DTMF '1' -->\n"
3165 " <nop>\n"
3166 " <action>\n"
3167 " <exec play_pcap_audio=\"/usr/local/share/sipp/pcap/dtmf_2833_1.pcap\"/>\n"
3168 " </action>\n"
3169 " </nop>\n"
3170 "\n"
3171 " <pause milliseconds=\"1000\"/>\n"
3172 "\n"
3173 " <!-- The 'crlf' option inserts a blank line in the statistics report. -->\n"
3174 " <send retrans=\"500\">\n"
3175 " <![CDATA[\n"
3176 "\n"
3177 " BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"
3178 " Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
3179 " From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag09[call_number]\n"
3180 " To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n"
3181 " Call-ID: [call_id]\n"
3182 " CSeq: 2 BYE\n"
3183 " Contact: sip:sipp@[local_ip]:[local_port]\n"
3184 " Max-Forwards: 70\n"
3185 " Subject: Performance Test\n"
3186 " Content-Length: 0\n"
3187 "\n"
3188 " ]]>\n"
3189 " </send>\n"
3190 "\n"
3191 " <recv response=\"200\" crlf=\"true\">\n"
3192 " </recv>\n"
3193 "\n"
3194 " <!-- definition of the response time repartition table (unit is ms) -->\n"
3195 " <ResponseTimeRepartition value=\"10, 20, 30, 40, 50, 100, 150, 200\"/>\n"
3196 "\n"
3197 " <!-- definition of the call length repartition table (unit is ms) -->\n"
3198 " <CallLengthRepartition value=\"10, 50, 100, 500, 1000, 5000, 10000\"/>\n"
3199 "\n"
3200 "</scenario>\n"
3201 "\n",
3202 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n"
3203 "<!DOCTYPE scenario SYSTEM \"sipp.dtd\">\n"
3204 "\n"
3205 "<!-- This program is free software; you can redistribute it and/or -->\n"
3206 "<!-- modify it under the terms of the GNU General Public License as -->\n"
3207 "<!-- published by the Free Software Foundation; either version 2 of the -->\n"
3208 "<!-- License, or (at your option) any later version. -->\n"
3209 "<!-- -->\n"
3210 "<!-- This program is distributed in the hope that it will be useful, -->\n"
3211 "<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->\n"
3212 "<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->\n"
3213 "<!-- GNU General Public License for more details. -->\n"
3214 "<!-- -->\n"
3215 "<!-- You should have received a copy of the GNU General Public License -->\n"
3216 "<!-- along with this program; if not, write to the -->\n"
3217 "<!-- Free Software Foundation, Inc., -->\n"
3218 "<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->\n"
3219 "<!-- -->\n"
3220 "<!-- Sipp default 'uas' scenario. -->\n"
3221 "<!-- -->\n"
3222 "\n"
3223 "<scenario name=\"Out-of-call UAS\">\n"
3224 " <recv request=\".*\" regexp_match=\"true\" />\n"
3225 "\n"
3226 " <send>\n"
3227 " <![CDATA[\n"
3228 " SIP/2.0 200 OK\n"
3229 " [last_Via:]\n"
3230 " [last_From:]\n"
3231 " [last_To:]\n"
3232 " [last_Call-ID:]\n"
3233 " [last_CSeq:]\n"
3234 " Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"
3235 " Content-Length: 0\n"
3236 "\n"
3237 " ]]>\n"
3238 " </send>\n"
3239 "\n"
3240 " <!-- Keep the call open for a while in case the 200 is lost to be -->\n"
3241 " <!-- able to retransmit it if we receive the BYE again. -->\n"
3242 " <timewait milliseconds=\"4000\"/>\n"
3243 "\n"
3244 "\n"
3245 " <!-- definition of the response time repartition table (unit is ms) -->\n"
3246 " <ResponseTimeRepartition value=\"10, 20, 30, 40, 50, 100, 150, 200\"/>\n"
3247 "\n"
3248 " <!-- definition of the call length repartition table (unit is ms) -->\n"
3249 " <CallLengthRepartition value=\"10, 50, 100, 500, 1000, 5000, 10000\"/>\n"
3250 "\n"
3251 "</scenario>\n",
3252 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n"
3253 "<!DOCTYPE scenario SYSTEM \"sipp.dtd\">\n"
3254 "\n"
3255 "<!-- This program is free software; you can redistribute it and/or -->\n"
3256 "<!-- modify it under the terms of the GNU General Public License as -->\n"
3257 "<!-- published by the Free Software Foundation; either version 2 of the -->\n"
3258 "<!-- License, or (at your option) any later version. -->\n"
3259 "<!-- -->\n"
3260 "<!-- This program is distributed in the hope that it will be useful, -->\n"
3261 "<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->\n"
3262 "<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->\n"
3263 "<!-- GNU General Public License for more details. -->\n"
3264 "<!-- -->\n"
3265 "<!-- You should have received a copy of the GNU General Public License -->\n"
3266 "<!-- along with this program; if not, write to the -->\n"
3267 "<!-- Free Software Foundation, Inc., -->\n"
3268 "<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->\n"
3269 "<!-- -->\n"
3270 "<!-- Sipp default 'uas' scenario. -->\n"
3271 "<!-- -->\n"
3272 "\n"
3273 "<scenario name=\"Out-of-call UAS\">\n"
3274 " <recv request=\"DUMMY\" />\n"
3275 "\n"
3276 " <!-- definition of the response time repartition table (unit is ms) -->\n"
3277 " <ResponseTimeRepartition value=\"10, 20, 30, 40, 50, 100, 150, 200\"/>\n"
3278 "\n"
3279 " <!-- definition of the call length repartition table (unit is ms) -->\n"
3280 " <CallLengthRepartition value=\"10, 50, 100, 500, 1000, 5000, 10000\"/>\n"
3281 "\n"
3282 "</scenario>\n",
3283 };
3284