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 * Eric Miller
22 * Venkatesh
23 * Enrico Hartung
24 * Nasir Khan
25 * Lee Ballard
26 * Guillaume Teissier from FTR&D
27 * Wolfgang Beck
28 * Venkatesh
29 * Vlad Troyanker
30 * Charles P Wright from IBM Research
31 * Amit On from Followap
32 * Jan Andres from Freenet
33 * Ben Evans from Open Cloud
34 * Marc Van Diest from Belgacom
35 * Michael Dwyer from Cibation
36 * Roland Meub
37 * Andy Aicken
38 * Martin H. VanLeeuwen
39 */
40
41 #include <iterator>
42 #include <algorithm>
43 #include <fstream>
44 #include <iostream>
45 #include <cstring>
46 #include <sys/types.h>
47 #include <sys/wait.h>
48 #include <assert.h>
49
50 #ifdef PCAPPLAY
51 #include "send_packets.h"
52 #endif
53 #include "sipp.hpp"
54 #include "auth.hpp"
55 #include "deadcall.hpp"
56 #include "config.h"
57 #include "version.h"
58
59 #define callDebug(...) do { if (useCallDebugf) { _callDebug( __VA_ARGS__ ); } } while (0)
60
61 extern map<string, struct sipp_socket *> map_perip_fd;
62
63 #ifdef PCAPPLAY
64 /* send_packets pthread wrapper */
65 void *send_wrapper(void *);
66 #endif
67 int call::dynamicId = 0;
68 int call::maxDynamicId = 10000+2000*4; // FIXME both param to be in command line !!!!
69 int call::startDynamicId = 10000; // FIXME both param to be in command line !!!!
70 int call::stepDynamicId = 4; // FIXME both param to be in command line !!!!
71
72 /************** Call map and management routines **************/
73 static unsigned int next_number = 1;
74
get_tdm_map_number()75 static unsigned int get_tdm_map_number()
76 {
77 unsigned int nb = 0;
78 unsigned int i=0;
79 unsigned int interval=0;
80 unsigned int random=0;
81 bool found = false;
82
83 /* Find a number in the tdm_map which is not in use */
84 interval = (tdm_map_a+1) * (tdm_map_b+1) * (tdm_map_c+1);
85 random = rand() % interval;
86 while ((i<interval) && (!found)) {
87 if (tdm_map[(random + i - 1) % interval] == false) {
88 nb = (random + i - 1) % interval;
89 found = true;
90 }
91 i++;
92 }
93
94 if (!found) {
95 return 0;
96 } else {
97 return nb+1;
98 }
99 }
100
101 /* When should this call wake up? */
wake()102 unsigned int call::wake()
103 {
104 unsigned int wake = 0;
105
106 if (zombie) {
107 return wake;
108 }
109
110 if (paused_until) {
111 wake = paused_until;
112 }
113
114 if (next_retrans && (!wake || (next_retrans < wake))) {
115 wake = next_retrans;
116 }
117
118 if (recv_timeout && (!wake || (recv_timeout < wake))) {
119 wake = recv_timeout;
120 }
121
122 return wake;
123 }
124
125 #ifdef PCAPPLAY
find_sdp_eol(char * line)126 static char* find_sdp_eol(char* line)
127 {
128 char* end = &line[strcspn(line, "\r\n")];
129 return end[0] == '\0' ? NULL : end;
130 }
131
132 /******* Media information management *************************/
133 /*
134 * Look for "c=IN IP4 " pattern in the message and extract the following value
135 * which should be IP address
136 */
get_remote_ip_media(char * msg)137 uint32_t get_remote_ip_media(char *msg)
138 {
139 char pattern[] = "c=IN IP4 ";
140 char *begin, *end;
141 char ip[32];
142 char *my_msg = strdup(msg);
143
144 if (!my_msg) {
145 return INADDR_NONE;
146 }
147 begin = strstr(my_msg, pattern);
148 if (!begin) {
149 free(my_msg);
150 /* Can't find what we're looking at -> return no address */
151 return INADDR_NONE;
152 }
153 begin += sizeof(pattern) - 1;
154 end = find_sdp_eol(begin);
155 if (!end) {
156 free(my_msg);
157 return INADDR_NONE;
158 }
159 *end = '\0';
160 memset(ip, 0, 32);
161 strncpy(ip, begin, sizeof(ip) - 1);
162 ip[sizeof(ip) - 1] = '\0';
163 free(my_msg);
164 return inet_addr(ip);
165 }
166
167 /*
168 * Look for "c=IN IP6 " pattern in the message and extract the following value
169 * which should be IPv6 address
170 */
get_remote_ipv6_media(char * msg,struct in6_addr * addr)171 uint8_t get_remote_ipv6_media(char *msg, struct in6_addr *addr)
172 {
173 char pattern[] = "c=IN IP6 ";
174 char *begin, *end;
175 char ip[128];
176 char *my_msg = strdup(msg);
177
178 memset(addr, 0, sizeof(*addr));
179 memset(ip, 0, 128);
180
181 if (!my_msg) {
182 return 0;
183 }
184 begin = strstr(my_msg,pattern);
185 if (!begin) {
186 free(my_msg);
187 /* Can't find what we're looking at -> return no address */
188 return 0;
189 }
190 begin += sizeof(pattern) - 1;
191 end = find_sdp_eol(begin);
192 if (!end) {
193 free(my_msg);
194 return 0;
195 }
196 *end = '\0';
197 strncpy(ip, begin, sizeof(ip) -1);
198 ip[sizeof(ip) - 1] = '\0';
199 free(my_msg);
200 if (!inet_pton(AF_INET6, ip, addr)) {
201 return 0;
202 }
203 return 1;
204 }
205
206 /*
207 * Look for "m=audio ", "m=image " or "m=video " pattern in the message
208 * and extract the following value which should be port number.
209 */
210 enum media_ptn {
211 PAT_AUDIO,
212 PAT_IMAGE,
213 PAT_VIDEO
214 };
get_remote_port_media(const char * msg,enum media_ptn pattype)215 uint16_t get_remote_port_media(const char *msg, enum media_ptn pattype)
216 {
217 const char *pattern;
218 char *begin, *end;
219 char number[6];
220
221 if (pattype == PAT_AUDIO) {
222 pattern = "m=audio ";
223 } else if (pattype == PAT_IMAGE) {
224 pattern = "m=image ";
225 } else if (pattype == PAT_VIDEO) {
226 pattern = "m=video ";
227 } else {
228 ERROR("Internal error: Undefined media pattern %d\n", 3);
229 }
230
231 char *my_msg = strdup(msg);
232 if (!my_msg) {
233 return 0;
234 }
235 begin = strstr(my_msg, pattern);
236 if (!begin) {
237 free(my_msg);
238 /* m=audio not found */
239 return 0;
240 }
241 begin += strlen(pattern);
242 end = find_sdp_eol(begin);
243 if (!end) {
244 free(my_msg);
245 ERROR("get_remote_port_media: no CRLF found");
246 return 0;
247 }
248 *end = '\0';
249 memset(number, 0, sizeof(number));
250 strncpy(number, begin, sizeof(number) - 1);
251 number[sizeof(number) - 1] = '\0';
252 free(my_msg);
253 return atoi(number);
254 }
255
256 /*
257 * IPv{4,6} compliant
258 */
get_remote_media_addr(char * msg)259 void call::get_remote_media_addr(char *msg)
260 {
261 uint16_t audio_port, image_port, video_port;
262 if (media_ip_is_ipv6) {
263 struct in6_addr ip_media;
264 if (get_remote_ipv6_media(msg, &ip_media)) {
265 audio_port = get_remote_port_media(msg, PAT_AUDIO);
266 if (audio_port) {
267 /* We have audio in the SDP: set the to_audio addr */
268 (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_flowinfo = 0;
269 (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_scope_id = 0;
270 (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_family = AF_INET6;
271 (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_port = htons(audio_port);
272 (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_addr = ip_media;
273 }
274 image_port = get_remote_port_media(msg, PAT_IMAGE);
275 if (image_port) {
276 /* We have image in the SDP: set the to_image addr */
277 (_RCAST(struct sockaddr_in6 *, &(play_args_i.to)))->sin6_flowinfo = 0;
278 (_RCAST(struct sockaddr_in6 *, &(play_args_i.to)))->sin6_scope_id = 0;
279 (_RCAST(struct sockaddr_in6 *, &(play_args_i.to)))->sin6_family = AF_INET6;
280 (_RCAST(struct sockaddr_in6 *, &(play_args_i.to)))->sin6_port = htons(image_port);
281 (_RCAST(struct sockaddr_in6 *, &(play_args_i.to)))->sin6_addr = ip_media;
282 }
283 video_port = get_remote_port_media(msg, PAT_VIDEO);
284 if (video_port) {
285 /* We have video in the SDP: set the to_video addr */
286 (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_flowinfo = 0;
287 (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_scope_id = 0;
288 (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_family = AF_INET6;
289 (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_port = htons(video_port);
290 (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_addr = ip_media;
291 }
292 hasMediaInformation = 1;
293 }
294 } else {
295 uint32_t ip_media;
296 ip_media = get_remote_ip_media(msg);
297 if (ip_media != INADDR_NONE) {
298 audio_port = get_remote_port_media(msg, PAT_AUDIO);
299 if (audio_port) {
300 /* We have audio in the SDP: set the to_audio addr */
301 (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_family = AF_INET;
302 (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_port = htons(audio_port);
303 (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_addr.s_addr = ip_media;
304 }
305 image_port = get_remote_port_media(msg, PAT_IMAGE);
306 if (image_port) {
307 /* We have image in the SDP: set the to_image addr */
308 (_RCAST(struct sockaddr_in *, &(play_args_i.to)))->sin_family = AF_INET;
309 (_RCAST(struct sockaddr_in *, &(play_args_i.to)))->sin_port = htons(image_port);
310 (_RCAST(struct sockaddr_in *, &(play_args_i.to)))->sin_addr.s_addr = ip_media;
311 }
312 video_port = get_remote_port_media(msg, PAT_VIDEO);
313 if (video_port) {
314 /* We have video in the SDP: set the to_video addr */
315 (_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_family = AF_INET;
316 (_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_port = htons(video_port);
317 (_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_addr.s_addr = ip_media;
318 }
319 hasMediaInformation = 1;
320 }
321 }
322 }
323
324 #endif
325
326 #ifdef RTP_STREAM
327 /******* Extract RTP remote media infomartion from SDP *******/
328 /***** Similar to the routines used by the PCAP play code *****/
329
330 #define SDP_IPADDR_PREFIX "\nc=IN IP"
331 #define SDP_AUDIOPORT_PREFIX "\nm=audio"
332 #define SDP_IMAGEPORT_PREFIX "\nm=image"
333 #define SDP_VIDEOPORT_PREFIX "\nm=video"
extract_rtp_remote_addr(char * msg)334 void call::extract_rtp_remote_addr (char * msg)
335 {
336 char *search;
337 char *copy;
338 char ip_addr[128];
339 int ip_ver;
340 int audio_port = 0;
341 int image_port = 0;
342 int video_port = 0;
343
344 /* Look for start of message body */
345 search= strstr(msg,"\r\n\r\n");
346 if (!search) {
347 ERROR("extract_rtp_remote_addr: SDP message body not found");
348 }
349 msg = search + 2; /* skip past header. point to blank line before body */
350 /* Now search for IP address field */
351 search= strstr(msg,SDP_IPADDR_PREFIX);
352 if (search) {
353 search+= strlen(SDP_IPADDR_PREFIX);
354 /* Get IP version number from c= */
355 if (*search=='4') {
356 ip_ver= 4;
357 } else if (*search=='6') {
358 ip_ver= 6;
359 } else {
360 ERROR("extract_rtp_remote_addr: invalid IP version '%c' in SDP message body",*search);
361 }
362 search++;
363 copy= ip_addr;
364 while ( (*search==' ') || (*search=='\t') ) {
365 search++;
366 }
367 while (!( (*search==' ') || (*search=='\t') || (*search=='\r') || (*search=='\n') )) {
368 *(copy++)= *(search++);
369 }
370 *copy= 0;
371 } else {
372 ERROR("extract_rtp_remote_addr: no IP address found in SDP message body");
373 *ip_addr= 0;
374 }
375 /* Now try to find the port number for the audio stream */
376 search= strstr(msg,SDP_AUDIOPORT_PREFIX);
377 if (search) {
378 search+= strlen(SDP_AUDIOPORT_PREFIX);
379 while ( (*search==' ') || (*search=='\t') ) {
380 search++;
381 }
382 sscanf (search,"%d",&audio_port);
383 }
384 /* And find the port number for the image stream */
385 search= strstr(msg,SDP_IMAGEPORT_PREFIX);
386 if (search) {
387 search+= strlen(SDP_IMAGEPORT_PREFIX);
388 while ( (*search==' ') || (*search=='\t') ) {
389 search++;
390 }
391 sscanf (search,"%d",&image_port);
392 }
393 /* And find the port number for the video stream */
394 search= strstr(msg,SDP_VIDEOPORT_PREFIX);
395 if (search) {
396 search+= strlen(SDP_VIDEOPORT_PREFIX);
397 while ( (*search==' ') || (*search=='\t') ) {
398 search++;
399 }
400 sscanf (search,"%d",&video_port);
401 }
402 if (audio_port == 0 && image_port == 0 && video_port == 0) {
403 ERROR("extract_rtp_remote_addr: no m=audio, m=image or m=video line found in SDP message body");
404 }
405 /* If we get an image_port only, we won't set anything useful.
406 * We cannot use rtpstream for udptl/t38 data because it has
407 * non-linear timing and data size. */
408 rtpstream_set_remote(&rtpstream_callinfo, ip_ver, ip_addr, audio_port, video_port);
409 }
410 #endif
411
412 /******* Very simple hash for retransmission detection *******/
413
hash(const char * msg)414 unsigned long call::hash(const char * msg)
415 {
416 unsigned long hash = 0;
417 int c;
418
419 if (rtcheck == RTCHECK_FULL) {
420 while ((c = *msg++))
421 hash = c + (hash << 6) + (hash << 16) - hash;
422 } else if (rtcheck == RTCHECK_LOOSE) {
423 /* Based on section 11.5 (bullet 2) of RFC2543 we only take into account
424 * the To, From, Call-ID, and CSeq values. */
425 const char *hdr = get_header_content(msg,"To:");
426 while ((c = *hdr++))
427 hash = c + (hash << 6) + (hash << 16) - hash;
428 hdr = get_header_content(msg,"From:");
429 while ((c = *hdr++))
430 hash = c + (hash << 6) + (hash << 16) - hash;
431 hdr = get_header_content(msg,"Call-ID:");
432 while ((c = *hdr++))
433 hash = c + (hash << 6) + (hash << 16) - hash;
434 hdr = get_header_content(msg,"CSeq:");
435 while ((c = *hdr++))
436 hash = c + (hash << 6) + (hash << 16) - hash;
437 /* For responses, we should also consider the code and body (if any),
438 * because they are not nearly as well defined as the request retransmission. */
439 if (!strncmp(msg, "SIP/2.0", strlen("SIP/2.0"))) {
440 /* Add the first line into the hash. */
441 hdr = msg + strlen("SIP/2.0");
442 while ((c = *hdr++) && (c != '\r'))
443 hash = c + (hash << 6) + (hash << 16) - hash;
444 /* Add the body (if any) into the hash. */
445 hdr = strstr(msg, "\r\n\r\n");
446 if (hdr) {
447 hdr += strlen("\r\n\r\n");
448 while ((c = *hdr++))
449 hash = c + (hash << 6) + (hash << 16) - hash;
450 }
451 }
452 } else {
453 ERROR("Internal error: Invalid rtcheck %d\n", rtcheck);
454 }
455
456 return hash;
457 }
458
459 /******************* Call class implementation ****************/
call(const char * p_id,bool use_ipv6,int userId,struct sockaddr_storage * dest)460 call::call(const char *p_id, bool use_ipv6, int userId, struct sockaddr_storage *dest) : listener(p_id, true)
461 {
462 init(main_scenario, NULL, dest, p_id, userId, use_ipv6, false, false);
463 }
464
call(const char * p_id,struct sipp_socket * socket,struct sockaddr_storage * dest)465 call::call(const char *p_id, struct sipp_socket *socket, struct sockaddr_storage *dest) : listener(p_id, true)
466 {
467 init(main_scenario, socket, dest, p_id, 0 /* No User. */, socket->ss_ipv6, false /* Not Auto. */, false);
468 }
469
call(scenario * call_scenario,struct sipp_socket * socket,struct sockaddr_storage * dest,const char * p_id,int userId,bool ipv6,bool isAutomatic,bool isInitialization)470 call::call(scenario * call_scenario, struct sipp_socket *socket, struct sockaddr_storage *dest, const char * p_id, int userId, bool ipv6, bool isAutomatic, bool isInitialization) : listener(p_id, true)
471 {
472 init(call_scenario, socket, dest, p_id, userId, ipv6, isAutomatic, isInitialization);
473 }
474
add_call(int userId,bool ipv6,struct sockaddr_storage * dest)475 call *call::add_call(int userId, bool ipv6, struct sockaddr_storage *dest)
476 {
477 static char call_id[MAX_HEADER_LEN];
478
479 const char * src = call_id_string;
480 int count = 0;
481
482 if(!next_number) {
483 next_number ++;
484 }
485
486 while (*src && count < MAX_HEADER_LEN-1) {
487 if (*src == '%') {
488 ++src;
489 switch(*src++) {
490 case 'u':
491 count += snprintf(&call_id[count], MAX_HEADER_LEN-count-1,"%u", next_number);
492 break;
493 case 'p':
494 count += snprintf(&call_id[count], MAX_HEADER_LEN-count-1,"%u", pid);
495 break;
496 case 's':
497 count += snprintf(&call_id[count], MAX_HEADER_LEN-count-1,"%s", local_ip);
498 break;
499 default: // treat all unknown sequences as %%
500 call_id[count++] = '%';
501 break;
502 }
503 } else {
504 call_id[count++] = *src++;
505 }
506 }
507 call_id[count] = 0;
508
509 return new call(main_scenario, NULL, dest, call_id, userId, ipv6, false /* Not Auto. */, false);
510 }
511
512
init(scenario * call_scenario,struct sipp_socket * socket,struct sockaddr_storage * dest,const char * p_id,int userId,bool ipv6,bool isAutomatic,bool isInitCall)513 void call::init(scenario * call_scenario, struct sipp_socket *socket, struct sockaddr_storage *dest, const char * p_id, int userId, bool ipv6, bool isAutomatic, bool isInitCall)
514 {
515 this->call_scenario = call_scenario;
516 zombie = false;
517
518 debugBuffer = NULL;
519 debugLength = 0;
520
521 msg_index = 0;
522 last_send_index = 0;
523 last_send_msg = NULL;
524 last_send_len = 0;
525
526 last_recv_hash = 0;
527 last_recv_index = -1;
528 last_recv_msg = NULL;
529
530 recv_retrans_hash = 0;
531 recv_retrans_recv_index = -1;
532 recv_retrans_send_index = -1;
533
534 dialog_route_set = NULL;
535 next_req_url = NULL;
536
537 cseq = 0;
538
539 next_retrans = 0;
540 nb_retrans = 0;
541 nb_last_delay = 0;
542
543 paused_until = 0;
544
545 call_port = 0;
546 comp_state = NULL;
547
548 start_time = clock_tick;
549 call_established=false ;
550 ack_is_pending=false ;
551 last_recv_msg = NULL;
552 cseq = base_cseq;
553 nb_last_delay = 0;
554 use_ipv6 = ipv6;
555 queued_msg = NULL;
556
557 dialog_authentication = NULL;
558 dialog_challenge_type = 0;
559
560 #ifdef USE_OPENSSL
561 m_ctx_ssl = NULL ;
562 m_bio = NULL ;
563 #endif
564 #ifdef RTP_STREAM
565 /* check and warn on rtpstream_new_call result? -> error alloc'ing mem */
566 rtpstream_new_call (&rtpstream_callinfo);
567 #endif
568
569 #ifdef PCAPPLAY
570 hasMediaInformation = 0;
571 #endif
572
573 call_remote_socket = NULL;
574 if (socket) {
575 associate_socket(socket);
576 socket->ss_count++;
577 } else {
578 call_socket = NULL;
579 }
580 if (dest) {
581 memcpy(&call_peer, dest, SOCK_ADDR_SIZE(dest));
582 } else {
583 memset(&call_peer, 0, sizeof(call_peer));
584 }
585
586 // initialising the CallVariable with the Scenario variable
587 int i;
588 VariableTable *userVars = NULL;
589 bool putUserVars = false;
590 if (userId) {
591 int_vt_map::iterator it = userVarMap.find(userId);
592 if (it != userVarMap.end()) {
593 userVars = it->second;
594 }
595 } else {
596 userVars = new VariableTable(userVariables);
597 /* Creating this table creates a reference to it, but if it is really used,
598 * then the refcount will be increased. */
599 putUserVars = true;
600 }
601 if (call_scenario->allocVars->size > 0) {
602 M_callVariableTable = new VariableTable(userVars, call_scenario->allocVars->size);
603 } else if (userVars && userVars->size > 0) {
604 M_callVariableTable = userVars->getTable();
605 } else if (globalVariables->size > 0) {
606 M_callVariableTable = globalVariables->getTable();
607 } else {
608 M_callVariableTable = NULL;
609 }
610 if (putUserVars) {
611 userVars->putTable();
612 }
613
614 if (call_scenario->transactions.size() > 0) {
615 transactions = (struct txnInstanceInfo *)malloc(sizeof(txnInstanceInfo) * call_scenario->transactions.size());
616 memset(transactions, 0, sizeof(struct txnInstanceInfo) * call_scenario->transactions.size());
617 } else {
618 transactions = NULL;
619 }
620
621 // If not updated by a message we use the start time
622 // information to compute rtd information
623 start_time_rtd = (unsigned long long *)malloc(sizeof(unsigned long long) * call_scenario->stats->nRtds());
624 if (!start_time_rtd) {
625 ERROR("Could not allocate RTD times!");
626 }
627 rtd_done = (bool *)malloc(sizeof(bool) * call_scenario->stats->nRtds());
628 if (!start_time_rtd) {
629 ERROR("Could not allocate RTD done!");
630 }
631 for (i = 0; i < call_scenario->stats->nRtds(); i++) {
632 start_time_rtd[i] = getmicroseconds();
633 rtd_done[i] = false;
634 }
635
636 // by default, last action result is NO_ERROR
637 last_action_result = call::E_AR_NO_ERROR;
638
639 this->userId = userId;
640
641 /* For automatic answer calls to an out of call request, we must not */
642 /* increment the input files line numbers to not disturb */
643 /* the input files read mechanism (otherwise some lines risk */
644 /* to be systematically skipped */
645 if (!isAutomatic) {
646 m_lineNumber = new file_line_map();
647 for (file_map::iterator file_it = inFiles.begin();
648 file_it != inFiles.end();
649 file_it++) {
650 (*m_lineNumber)[file_it->first] = file_it->second->nextLine(userId);
651 }
652 } else {
653 m_lineNumber = NULL;
654 }
655 this->initCall = isInitCall;
656
657 #ifdef PCAPPLAY
658 memset(&(play_args_a.to), 0, sizeof(struct sockaddr_storage));
659 memset(&(play_args_i.to), 0, sizeof(struct sockaddr_storage));
660 memset(&(play_args_v.to), 0, sizeof(struct sockaddr_storage));
661 memset(&(play_args_a.from), 0, sizeof(struct sockaddr_storage));
662 memset(&(play_args_i.from), 0, sizeof(struct sockaddr_storage));
663 memset(&(play_args_v.from), 0, sizeof(struct sockaddr_storage));
664 hasMediaInformation = 0;
665 media_thread = 0;
666 #endif
667
668 peer_tag = NULL;
669 recv_timeout = 0;
670 send_timeout = 0;
671 timewait = false;
672
673 if (!isAutomatic) {
674 /* Not advancing the number is safe, because for automatic calls we do not
675 * assign the identifier, the only other place it is used is for the auto
676 * media port. */
677 number = next_number++;
678
679 if (use_tdmmap) {
680 tdm_map_number = get_tdm_map_number();
681 if (tdm_map_number == 0) {
682 /* Can't create the new call */
683 WARNING("Can't create new outgoing call: all tdm_map circuits busy");
684 computeStat(CStat::E_CALL_FAILED);
685 computeStat(CStat::E_FAILED_OUTBOUND_CONGESTION);
686 this->zombie = true;
687 return;
688 }
689 /* Mark the entry in the list as busy */
690 tdm_map[tdm_map_number - 1] = true;
691 } else {
692 tdm_map_number = 0;
693 }
694 }
695
696 callDebug("Starting call %s\n", id);
697
698 setRunning();
699 }
700
_callDebug(const char * fmt,...)701 int call::_callDebug(const char *fmt, ...)
702 {
703 va_list ap;
704
705 if (!useCallDebugf) {
706 return 0;
707 }
708
709 /* First we figure out how much to allocate. */
710 va_start(ap, fmt);
711 int ret = vsnprintf(NULL, 0, fmt, ap);
712 va_end(ap);
713
714 debugBuffer = (char *)realloc(debugBuffer, debugLength + ret + TIME_LENGTH + 2);
715 if (!debugBuffer) {
716 ERROR("Could not allocate buffer (%d bytes) for callDebug file!", debugLength + ret + TIME_LENGTH + 2);
717 }
718
719 struct timeval now;
720 gettimeofday(&now, NULL);
721 debugLength += snprintf(debugBuffer + debugLength, TIME_LENGTH + 2, "%s ", CStat::formatTime(&now));
722
723 va_start(ap, fmt);
724 debugLength += vsnprintf(debugBuffer + debugLength, ret + 1, fmt, ap);
725 va_end(ap);
726
727 return ret;
728 }
729
~call()730 call::~call()
731 {
732 computeStat(CStat::E_ADD_CALL_DURATION, clock_tick - start_time);
733
734 if(comp_state) {
735 comp_free(&comp_state);
736 }
737
738 if (call_remote_socket && (call_remote_socket != main_remote_socket)) {
739 sipp_close_socket(call_remote_socket);
740 }
741
742 /* Deletion of the call variable */
743 if(M_callVariableTable) {
744 M_callVariableTable->putTable();
745 }
746 if (m_lineNumber) {
747 delete m_lineNumber;
748 }
749 if (userId) {
750 CallGenerationTask::free_user(userId);
751 }
752
753 if (transactions) {
754 for (unsigned int i = 0; i < call_scenario->transactions.size(); i++) {
755 free(transactions[i].txnID);
756 }
757 free(transactions);
758 }
759
760 if(last_recv_msg) {
761 free(last_recv_msg);
762 }
763 if(last_send_msg) {
764 free(last_send_msg);
765 }
766 if(peer_tag) {
767 free(peer_tag);
768 }
769
770 if(dialog_route_set) {
771 free(dialog_route_set);
772 }
773
774 if(next_req_url) {
775 free(next_req_url);
776 }
777
778 #ifdef RTP_STREAM
779 rtpstream_end_call (&rtpstream_callinfo);
780 #endif
781
782 if(dialog_authentication) {
783 free(dialog_authentication);
784 }
785
786 if (use_tdmmap) {
787 tdm_map[tdm_map_number] = false;
788 }
789
790 # ifdef PCAPPLAY
791 if (media_thread != 0) {
792 pthread_cancel(media_thread);
793 pthread_join(media_thread, NULL);
794 }
795 #endif
796
797
798 free(start_time_rtd);
799 free(rtd_done);
800 free(debugBuffer);
801 }
802
computeStat(CStat::E_Action P_action)803 void call::computeStat (CStat::E_Action P_action)
804 {
805 if (initCall) {
806 return;
807 }
808 call_scenario->stats->computeStat(P_action);
809 }
810
computeStat(CStat::E_Action P_action,unsigned long P_value)811 void call::computeStat (CStat::E_Action P_action, unsigned long P_value)
812 {
813 if (initCall) {
814 return;
815 }
816 call_scenario->stats->computeStat(P_action, P_value);
817 }
818
computeStat(CStat::E_Action P_action,unsigned long P_value,int which)819 void call::computeStat (CStat::E_Action P_action, unsigned long P_value, int which)
820 {
821 if (initCall) {
822 return;
823 }
824 call_scenario->stats->computeStat(P_action, P_value, which);
825 }
826
827 /* Dump call info to error log. */
dump()828 void call::dump()
829 {
830 char s[MAX_HEADER_LEN];
831 char tmpbuf[MAX_HEADER_LEN];
832 sprintf(s, "%s: State %d", id, msg_index);
833 if (next_retrans) {
834 snprintf(tmpbuf, 64, "%s (next retrans %u)", s, next_retrans);
835 strcat(s, tmpbuf);
836 }
837 if (paused_until) {
838 snprintf(tmpbuf, 64, "%s (paused until %u)", s, paused_until);
839 strcat(s, tmpbuf);
840 }
841 if (recv_timeout) {
842 snprintf(tmpbuf, 64, "%s (recv timeout %u)", s, recv_timeout);
843 strcat(s, tmpbuf);
844 }
845 if (send_timeout) {
846 snprintf(tmpbuf, 64, "%s (send timeout %u)", s, send_timeout);
847 strcat(s, tmpbuf);
848 }
849 WARNING("%s", s);
850 }
851
connect_socket_if_needed()852 bool call::connect_socket_if_needed()
853 {
854 bool existing;
855
856 if(call_socket) return true;
857 if(!multisocket) return true;
858
859 if(transport == T_UDP) {
860 struct sockaddr_storage saddr;
861
862 if(sendMode != MODE_CLIENT)
863 return true;
864
865 char peripaddr[256];
866 if (!peripsocket) {
867 if ((associate_socket(new_sipp_call_socket(use_ipv6, transport, &existing))) == NULL) {
868 ERROR_NO("Unable to get a UDP socket (1)");
869 }
870 } else {
871 char *tmp = peripaddr;
872 getFieldFromInputFile(ip_file, peripfield, NULL, tmp);
873 map<string, struct sipp_socket *>::iterator i;
874 i = map_perip_fd.find(peripaddr);
875 if (i == map_perip_fd.end()) {
876 // Socket does not exist
877 if ((associate_socket(new_sipp_call_socket(use_ipv6, transport, &existing))) == NULL) {
878 ERROR_NO("Unable to get a UDP socket (2)");
879 } else {
880 /* Ensure that it stays persistent, because it is recorded in the map. */
881 call_socket->ss_count++;
882 map_perip_fd[peripaddr] = call_socket;
883 }
884 } else {
885 // Socket exists already
886 associate_socket(i->second);
887 existing = true;
888 i->second->ss_count++;
889 }
890 }
891 if (existing) {
892 return true;
893 }
894
895 memset(&saddr, 0, sizeof(struct sockaddr_storage));
896
897 memcpy(&saddr,
898 local_addr_storage->ai_addr,
899 SOCK_ADDR_SIZE(
900 _RCAST(struct sockaddr_storage *,local_addr_storage->ai_addr)));
901
902 if (use_ipv6) {
903 saddr.ss_family = AF_INET6;
904 } else {
905 saddr.ss_family = AF_INET;
906 }
907
908 if (peripsocket) {
909 struct addrinfo * h ;
910 struct addrinfo hints;
911 memset((char*)&hints, 0, sizeof(hints));
912 hints.ai_flags = AI_PASSIVE;
913 hints.ai_family = PF_UNSPEC;
914 getaddrinfo(peripaddr,
915 NULL,
916 &hints,
917 &h);
918 memcpy(&saddr, h->ai_addr,
919 SOCK_ADDR_SIZE(_RCAST(struct sockaddr_storage*, h->ai_addr)));
920
921 if (use_ipv6) {
922 (_RCAST(struct sockaddr_in6*, &saddr))->sin6_port = htons(local_port);
923 } else {
924 (_RCAST(struct sockaddr_in*, &saddr))->sin_port = htons(local_port);
925 }
926 freeaddrinfo(h);
927 }
928
929 if (sipp_bind_socket(call_socket, &saddr, &call_port)) {
930 ERROR_NO("Unable to bind UDP socket");
931 }
932 } else { /* TCP, SCTP or TLS. */
933 struct sockaddr_storage *L_dest = &remote_sockaddr;
934
935 if ((associate_socket(new_sipp_call_socket(use_ipv6, transport, &existing))) == NULL) {
936 ERROR_NO("Unable to get a TCP/SCTP/TLS socket");
937 }
938
939 if (existing) {
940 return true;
941 }
942
943 sipp_customize_socket(call_socket);
944
945 if (use_remote_sending_addr) {
946 L_dest = &remote_sending_sockaddr;
947 }
948
949 if (sipp_connect_socket(call_socket, L_dest)) {
950 if (reconnect_allowed()) {
951 if(errno == EINVAL) {
952 /* This occurs sometime on HPUX but is not a true INVAL */
953 WARNING("Unable to connect a TCP/SCTP/TLS socket, remote peer error");
954 } else {
955 WARNING("Unable to connect a TCP/SCTP/TLS socket");
956 }
957 /* This connection failed. We must be in multisocket mode, because
958 * otherwise we would already have a call_socket. This call can not
959 * succeed, but does not affect any of our other calls. We do decrement
960 * the reconnection counter however. */
961 if (reset_number != -1) {
962 reset_number--;
963 }
964
965 computeStat(CStat::E_CALL_FAILED);
966 computeStat(CStat::E_FAILED_TCP_CONNECT);
967 delete this;
968
969 return false;
970 } else {
971 if(errno == EINVAL) {
972 /* This occurs sometime on HPUX but is not a true INVAL */
973 ERROR("Unable to connect a TCP/SCTP/TLS socket, remote peer error");
974 } else {
975 ERROR_NO("Unable to connect a TCP/SCTP/TLS socket");
976 }
977 }
978 }
979 }
980 return true;
981 }
982
lost(int index)983 bool call::lost(int index)
984 {
985 static int inited = 0;
986 double percent = global_lost;
987
988 if(!lose_packets) return false;
989
990 if (call_scenario->messages[index]->lost >= 0) {
991 percent = call_scenario->messages[index]->lost;
992 }
993
994 if (percent == 0) {
995 return false;
996 }
997
998 if(!inited) {
999 srand((unsigned int) time(NULL));
1000 inited = 1;
1001 }
1002
1003 return (((double)rand() / (double)RAND_MAX) < (percent / 100.0));
1004 }
1005
send_raw(const char * msg,int index,int len)1006 int call::send_raw(const char * msg, int index, int len)
1007 {
1008 struct sipp_socket *sock;
1009 int rc;
1010
1011 callDebug("Sending %s message for call %s (index %d, hash %lu):\n%s\n\n",
1012 TRANSPORT_TO_STRING(transport), id, index, hash(msg), msg);
1013
1014 if((index!=-1) && (lost(index))) {
1015 TRACE_MSG("%s message voluntary lost (while sending).", TRANSPORT_TO_STRING(transport));
1016 callDebug("%s message voluntary lost (while sending) (index %d, hash %lu).\n",
1017 TRANSPORT_TO_STRING(transport), index, hash(msg));
1018
1019 if(comp_state) {
1020 comp_free(&comp_state);
1021 }
1022 call_scenario->messages[index] -> nb_lost++;
1023 return 0;
1024 }
1025
1026 sock = call_socket;
1027
1028 if ((use_remote_sending_addr) && (sendMode == MODE_SERVER)) {
1029 if (!call_remote_socket) {
1030 if (multisocket || !main_remote_socket) {
1031 struct sockaddr_storage *L_dest = &remote_sending_sockaddr;
1032
1033 if((call_remote_socket= new_sipp_socket(use_ipv6, transport)) == NULL) {
1034 ERROR_NO("Unable to get a socket for rsa option");
1035 }
1036
1037 sipp_customize_socket(call_remote_socket);
1038
1039 if(transport != T_UDP) {
1040 if (sipp_connect_socket(call_remote_socket, L_dest)) {
1041 if(errno == EINVAL) {
1042 /* This occurs sometime on HPUX but is not a true INVAL */
1043 ERROR("Unable to connect a %s socket for rsa option, remote peer error", TRANSPORT_TO_STRING(transport));
1044 } else {
1045 ERROR_NO("Unable to connect a socket for rsa option");
1046 }
1047 }
1048 }
1049 if (!multisocket) {
1050 main_remote_socket = call_remote_socket;
1051 }
1052 }
1053
1054 if (!multisocket) {
1055 call_remote_socket = main_remote_socket;
1056 main_remote_socket->ss_count++;
1057 }
1058 }
1059 sock=call_remote_socket ;
1060 }
1061
1062 // If the length hasn't been explicitly specified, treat the message as a string
1063 if (len==0) {
1064 len = strlen(msg);
1065 }
1066
1067 assert(sock);
1068
1069 rc = write_socket(sock, msg, len, WS_BUFFER, &call_peer);
1070 if(rc < 0 && errno == EWOULDBLOCK) {
1071 return rc;
1072 }
1073
1074 if(rc < 0) {
1075 computeStat(CStat::E_CALL_FAILED);
1076 computeStat(CStat::E_FAILED_CANNOT_SEND_MSG);
1077 delete this;
1078 }
1079
1080 return rc; /* OK */
1081 }
1082
1083 /* This method is used to send messages that are not */
1084 /* part of the XML scenario */
sendBuffer(char * msg,int len)1085 void call::sendBuffer(char * msg, int len)
1086 {
1087 /* call send_raw but with a special scenario index */
1088 if (send_raw(msg, -1, len) < 0) {
1089 if (sendbuffer_warn) {
1090 ERROR_NO("Error sending raw message");
1091 } else {
1092 WARNING_NO("Error sending raw message");
1093 }
1094 }
1095 }
1096
get_header_field_code(const char * msg,const char * name)1097 char * call::get_header_field_code(const char *msg, const char * name)
1098 {
1099 static char code[MAX_HEADER_LEN];
1100 const char * last_header;
1101 int i;
1102
1103 last_header = NULL;
1104 i = 0;
1105 /* If we find the field in msg */
1106 last_header = get_header_content(msg, name);
1107 if(last_header) {
1108 /* Extract the integer value of the field */
1109 while(isspace(*last_header)) last_header++;
1110 sscanf(last_header,"%d", &i);
1111 sprintf(code, "%s %d", name, i);
1112 }
1113 return code;
1114 }
1115
get_last_header(const char * name)1116 char * call::get_last_header(const char * name)
1117 {
1118 int len;
1119
1120 if((!last_recv_msg) || (!strlen(last_recv_msg))) {
1121 return NULL;
1122 }
1123
1124 len = strlen(name);
1125
1126 /* Ideally this check should be moved to the XML parser so that it is not
1127 * along a critical path. We could also handle lowercasing there. */
1128 if (len > MAX_HEADER_LEN) {
1129 ERROR("call::get_last_header: Header to parse bigger than %d (%zu)", MAX_HEADER_LEN, strlen(name));
1130 }
1131
1132 if (name[len - 1] == ':') {
1133 return get_header(last_recv_msg, name, false);
1134 } else {
1135 char with_colon[MAX_HEADER_LEN];
1136 sprintf(with_colon, "%s:", name);
1137 return get_header(last_recv_msg, with_colon, false);
1138 }
1139 }
1140
1141 /* Return the last request URI from the To header. On any error returns the
1142 * empty string. The caller must free the result. */
get_last_request_uri()1143 char * call::get_last_request_uri()
1144 {
1145 char * tmp;
1146 char * tmp2;
1147 char * last_request_uri;
1148 int tmp_len;
1149
1150 char * last_To = get_last_header("To:");
1151 if (!last_To) {
1152 return strdup("");
1153 }
1154
1155 tmp = strchr(last_To, '<');
1156 if (!tmp) {
1157 return strdup("");
1158 }
1159 tmp++;
1160
1161 tmp2 = strchr(last_To, '>');
1162 if (!tmp2) {
1163 return strdup("");
1164 }
1165
1166 tmp_len = strlen(tmp) - strlen(tmp2);
1167 if (tmp_len < 0) {
1168 return strdup("");
1169 }
1170
1171 if (!(last_request_uri = (char *)malloc(tmp_len + 1))) {
1172 ERROR("Cannot allocate !\n");
1173 }
1174
1175 last_request_uri[0] = '\0';
1176 if (tmp && (tmp_len > 0)) {
1177 strncpy(last_request_uri, tmp, tmp_len);
1178 }
1179 last_request_uri[tmp_len] = '\0';
1180
1181 return last_request_uri;
1182 }
1183
send_scene(int index,int * send_status,int * len)1184 char * call::send_scene(int index, int *send_status, int *len)
1185 {
1186 #define MAX_MSG_NAME_SIZE 30
1187 static char msg_name[MAX_MSG_NAME_SIZE];
1188 char *L_ptr1 ;
1189 char *L_ptr2 ;
1190 int uselen = 0;
1191 int tmplen;
1192 char *hdrbdry;
1193
1194 assert(send_status);
1195
1196 /* Socket port must be known before string substitution */
1197 if (!connect_socket_if_needed()) {
1198 *send_status = -2;
1199 return NULL;
1200 }
1201
1202 assert(call_socket);
1203
1204 assert(call_scenario->messages[index]->send_scheme);
1205
1206 if (!len) {
1207 len = &uselen;
1208 }
1209
1210 char * dest;
1211 dest = createSendingMessage(call_scenario->messages[index] -> send_scheme, index, len);
1212
1213 if (!dest) {
1214 *send_status = -2;
1215 return NULL;
1216 }
1217
1218 L_ptr1=msg_name ;
1219 L_ptr2=dest ;
1220 while ((*L_ptr2 != ' ') && (*L_ptr2 != '\n') && (*L_ptr2 != '\t')) {
1221 *L_ptr1 = *L_ptr2;
1222 L_ptr1 ++;
1223 L_ptr2 ++;
1224 }
1225 *L_ptr1 = '\0' ;
1226
1227 if (strcmp(msg_name,"ACK") == 0) {
1228 call_established = true ;
1229 ack_is_pending = false ;
1230 }
1231
1232 /* Fix: Remove extra "\r\n" if message body ends with "\r\n\r\n" */
1233 tmplen = (*len) - 1;
1234 if ((dest[tmplen] == dest[tmplen-2] && dest[tmplen] == '\n')
1235 && (dest[tmplen-1] == dest[tmplen-3] && dest[tmplen-1] == '\r')) {
1236 hdrbdry = strstr(dest, "\r\n\r\n");
1237 if (NULL != hdrbdry && hdrbdry != dest+(tmplen-3)) {
1238 *len = (*len) - 2;
1239 }
1240 }
1241
1242 *send_status = send_raw(dest, index, *len);
1243
1244 return dest;
1245 }
1246
do_bookkeeping(message * curmsg)1247 void call::do_bookkeeping(message *curmsg)
1248 {
1249 /* If this message increments a counter, do it now. */
1250 if(int counter = curmsg -> counter) {
1251 computeStat(CStat::E_ADD_GENERIC_COUNTER, 1, counter - 1);
1252 }
1253
1254 /* If this message can be used to compute RTD, do it now */
1255 if(int rtd = curmsg -> start_rtd) {
1256 start_time_rtd[rtd - 1] = getmicroseconds();
1257 }
1258
1259 if(int rtd = curmsg -> stop_rtd) {
1260 if (!rtd_done[rtd - 1]) {
1261 unsigned long long start = start_time_rtd[rtd - 1];
1262 unsigned long long end = getmicroseconds();
1263
1264 if(dumpInRtt) {
1265 call_scenario->stats->computeRtt(start, end, rtd);
1266 }
1267
1268 computeStat(CStat::E_ADD_RESPONSE_TIME_DURATION,
1269 (end - start) / 1000, rtd - 1);
1270
1271 if (!curmsg -> repeat_rtd) {
1272 rtd_done[rtd - 1] = true;
1273 }
1274 }
1275 }
1276 }
1277
tcpClose()1278 void call::tcpClose()
1279 {
1280 terminate(CStat::E_FAILED_TCP_CLOSED);
1281 }
1282
terminate(CStat::E_Action reason)1283 void call::terminate(CStat::E_Action reason)
1284 {
1285 char reason_str[100];
1286
1287 stopListening();
1288
1289 // Call end -> was it successful?
1290 if(call::last_action_result != call::E_AR_NO_ERROR) {
1291 switch(call::last_action_result) {
1292 case call::E_AR_REGEXP_DOESNT_MATCH:
1293 computeStat(CStat::E_CALL_FAILED);
1294 computeStat(CStat::E_FAILED_REGEXP_DOESNT_MATCH);
1295 if (deadcall_wait && !initCall) {
1296 sprintf(reason_str, "regexp match failure at index %d", msg_index);
1297 new deadcall(id, reason_str);
1298 }
1299 break;
1300 case call::E_AR_REGEXP_SHOULDNT_MATCH:
1301 computeStat(CStat::E_CALL_FAILED);
1302 computeStat(CStat::E_FAILED_REGEXP_SHOULDNT_MATCH);
1303 if (deadcall_wait && !initCall) {
1304 sprintf(reason_str, "regexp matched, but shouldn't at index %d", msg_index);
1305 new deadcall(id, reason_str);
1306 }
1307 break;
1308 case call::E_AR_HDR_NOT_FOUND:
1309 computeStat(CStat::E_CALL_FAILED);
1310 computeStat(CStat::E_FAILED_REGEXP_HDR_NOT_FOUND);
1311 if (deadcall_wait && !initCall) {
1312 sprintf(reason_str, "regexp header not found at index %d", msg_index);
1313 new deadcall(id, reason_str);
1314 }
1315 break;
1316 case E_AR_CONNECT_FAILED:
1317 computeStat(CStat::E_CALL_FAILED);
1318 computeStat(CStat::E_FAILED_TCP_CONNECT);
1319 if (deadcall_wait && !initCall) {
1320 sprintf(reason_str, "connection failed %d", msg_index);
1321 new deadcall(id, reason_str);
1322 }
1323 break;
1324 case call::E_AR_NO_ERROR:
1325 case call::E_AR_STOP_CALL:
1326 /* Do nothing. */
1327 break;
1328 }
1329 } else {
1330 if (reason == CStat::E_CALL_SUCCESSFULLY_ENDED || timewait) {
1331 computeStat(CStat::E_CALL_SUCCESSFULLY_ENDED);
1332 if (deadcall_wait && !initCall) {
1333 new deadcall(id, "successful");
1334 }
1335 } else {
1336 computeStat(CStat::E_CALL_FAILED);
1337 if (reason != CStat::E_NO_ACTION) {
1338 computeStat(reason);
1339 }
1340 if (deadcall_wait && !initCall) {
1341 sprintf(reason_str, "failed at index %d", msg_index);
1342 new deadcall(id, reason_str);
1343 }
1344 }
1345 }
1346 delete this;
1347 }
1348
next()1349 bool call::next()
1350 {
1351 msgvec * msgs = &call_scenario->messages;
1352 if (initCall) {
1353 msgs = &call_scenario->initmessages;
1354 }
1355
1356 int test;
1357 /* What is the next message index? */
1358 /* Default without branching: use the next message */
1359 int new_msg_index = msg_index + 1;
1360 /* If branch needed, overwrite this default */
1361 if (msg_index >= 0 && ((*msgs)[msg_index]->next >= 0) &&
1362 (((test = ((*msgs)[msg_index]->test)) == -1) ||
1363 M_callVariableTable->getVar(test)->isSet())) {
1364 /* Branching possible, check the probability */
1365 int chance = (*msgs)[msg_index]->chance;
1366 if ((chance <= 0) || (rand() > chance )) {
1367 /* Branch == overwrite with the 'next' attribute value */
1368 new_msg_index = (*msgs)[msg_index]->next;
1369 }
1370 }
1371 msg_index = new_msg_index;
1372 recv_timeout = 0;
1373 if (msg_index >= (int)((*msgs).size())) {
1374 terminate(CStat::E_CALL_SUCCESSFULLY_ENDED);
1375 return false;
1376 }
1377
1378 return true;
1379 }
1380
executeMessage(message * curmsg)1381 bool call::executeMessage(message *curmsg)
1382 {
1383 if (curmsg->pause_distribution || curmsg->pause_variable != -1) {
1384 unsigned int pause;
1385 if (curmsg->pause_distribution) {
1386 double actualpause = curmsg->pause_distribution->sample();
1387 if (actualpause < 1) {
1388 // Protect against distribution samples that give
1389 // negative results (and so pause for ~50 hours when
1390 // cast to a unsigned int).
1391 pause = 0;
1392 } else {
1393 pause = (unsigned int)actualpause;
1394 };
1395 } else {
1396 int varId = curmsg->pause_variable;
1397 pause = (int) M_callVariableTable->getVar(varId)->getDouble();
1398 }
1399 if (pause > INT_MAX) {
1400 pause = INT_MAX;
1401 }
1402 paused_until = clock_tick + pause;
1403
1404 /* This state is used as the last message of a scenario, just for handling
1405 * final retransmissions. If the connection closes, we do not mark it is
1406 * failed. */
1407 this->timewait = curmsg->timewait;
1408
1409 /* Increment the number of sessions in pause state */
1410 curmsg->sessions++;
1411 do_bookkeeping(curmsg);
1412 executeAction(NULL, curmsg);
1413 callDebug("Pausing call until %d (is now %ld).\n", paused_until, clock_tick);
1414 setPaused();
1415 return true;
1416 } else if(curmsg -> M_type == MSG_TYPE_SENDCMD) {
1417 int send_status;
1418
1419 if(next_retrans) {
1420 return true;
1421 }
1422
1423 send_status = sendCmdMessage(curmsg);
1424
1425 if(send_status != 0) { /* Send error */
1426 return false; /* call deleted */
1427 }
1428 curmsg -> M_nbCmdSent++;
1429 next_retrans = 0;
1430
1431 do_bookkeeping(curmsg);
1432 executeAction(NULL, curmsg);
1433 return(next());
1434 } else if(curmsg -> M_type == MSG_TYPE_NOP) {
1435 callDebug("Executing NOP at index %d.\n", curmsg->index);
1436 do_bookkeeping(curmsg);
1437 executeAction(NULL, curmsg);
1438 return(next());
1439 }
1440
1441 else if(curmsg -> send_scheme) {
1442 char * msg_snd;
1443 int msgLen;
1444 int send_status;
1445
1446 /* Do not send a new message until the previous one which had
1447 * retransmission enabled is acknowledged */
1448
1449 if(next_retrans) {
1450 setPaused();
1451 return true;
1452 }
1453
1454 /* Handle counters and RTDs for this message. */
1455 do_bookkeeping(curmsg);
1456
1457 /* decide whether to increment cseq or not
1458 * basically increment for anything except response, ACK or CANCEL
1459 * Note that cseq is only used by the [cseq] keyword, and
1460 * not by default
1461 */
1462
1463 int incr_cseq = 0;
1464 if (!curmsg->send_scheme->isAck() &&
1465 !curmsg->send_scheme->isCancel() &&
1466 !curmsg->send_scheme->isResponse()) {
1467 ++cseq;
1468 incr_cseq = 1;
1469 }
1470
1471 msg_snd = send_scene(msg_index, &send_status, &msgLen);
1472 if(send_status < 0 && errno == EWOULDBLOCK) {
1473 if (incr_cseq) --cseq;
1474 /* Have we set the timeout yet? */
1475 if (send_timeout) {
1476 /* If we have actually timed out. */
1477 if (clock_tick > send_timeout) {
1478 WARNING("Call-Id: %s, send timeout on message %s:%d: aborting call",
1479 id, curmsg->desc, curmsg->index);
1480 computeStat(CStat::E_CALL_FAILED);
1481 computeStat(CStat::E_FAILED_TIMEOUT_ON_SEND);
1482 if (default_behaviors & DEFAULT_BEHAVIOR_BYE) {
1483 return (abortCall(true));
1484 } else {
1485 delete this;
1486 return false;
1487 }
1488 }
1489 } else if (curmsg->timeout) {
1490 /* Initialize the send timeout to the per message timeout. */
1491 send_timeout = clock_tick + curmsg->timeout;
1492 } else if (defl_send_timeout) {
1493 /* Initialize the send timeout to the global timeout. */
1494 send_timeout = clock_tick + defl_send_timeout;
1495 }
1496 return true; /* No step, nothing done, retry later */
1497 } else if(send_status < 0) { /* Send error */
1498 /* The call was already deleted by connect_socket_if_needed or send_raw,
1499 * so we should no longer access members. */
1500 return false;
1501 }
1502 /* We have sent the message, so the timeout is no longer needed. */
1503 send_timeout = 0;
1504
1505 last_send_index = curmsg->index;
1506 last_send_len = msgLen;
1507 realloc_ptr = (char *) realloc(last_send_msg, msgLen+1);
1508 if (realloc_ptr) {
1509 last_send_msg = realloc_ptr;
1510 } else {
1511 free(last_send_msg);
1512 ERROR("Out of memory!");
1513 return false;
1514 }
1515 memcpy(last_send_msg, msg_snd, msgLen);
1516 last_send_msg[msgLen] = '\0';
1517
1518 if (curmsg->start_txn) {
1519 transactions[curmsg->start_txn - 1].txnID = (char *)realloc(transactions[curmsg->start_txn - 1].txnID, MAX_HEADER_LEN);
1520 extract_transaction(transactions[curmsg->start_txn - 1].txnID, last_send_msg);
1521 }
1522 if (curmsg->ack_txn) {
1523 transactions[curmsg->ack_txn - 1].ackIndex = curmsg->index;
1524 }
1525
1526 if(last_recv_index >= 0) {
1527 /* We are sending just after msg reception. There is a great
1528 * chance that we will be asked to retransmit this message */
1529 recv_retrans_hash = last_recv_hash;
1530 recv_retrans_recv_index = last_recv_index;
1531 recv_retrans_send_index = curmsg->index;
1532
1533 callDebug("Set Retransmission Hash: %lu (recv index %d, send index %d)\n",
1534 recv_retrans_hash, recv_retrans_recv_index, recv_retrans_send_index);
1535
1536 /* Prevent from detecting the cause relation between send and recv
1537 * in the next valid send */
1538 last_recv_hash = 0;
1539 }
1540
1541 /* Update retransmission information */
1542 if(curmsg -> retrans_delay) {
1543 if((transport == T_UDP) && (retrans_enabled)) {
1544 next_retrans = clock_tick + curmsg -> retrans_delay;
1545 nb_retrans = 0;
1546 nb_last_delay = curmsg->retrans_delay;
1547 }
1548 } else {
1549 next_retrans = 0;
1550 }
1551
1552 executeAction(msg_snd, curmsg);
1553
1554 /* Update scenario statistics */
1555 curmsg -> nb_sent++;
1556
1557 return next();
1558 } else if (curmsg->M_type == MSG_TYPE_RECV
1559 || curmsg->M_type == MSG_TYPE_RECVCMD
1560 ) {
1561 if (queued_msg) {
1562 char *msg = queued_msg;
1563 queued_msg = NULL;
1564 bool ret = process_incoming(msg);
1565 free(msg);
1566 return ret;
1567 } else if (recv_timeout) {
1568 if(recv_timeout > getmilliseconds()) {
1569 setPaused();
1570 return true;
1571 }
1572 recv_timeout = 0;
1573 curmsg->nb_timeout++;
1574 if (curmsg->on_timeout < 0) {
1575 // if you set a timeout but not a label, the call is aborted
1576 WARNING("Call-Id: %s, receive timeout on message %s:%d without label to jump to (ontimeout attribute): aborting call",
1577 id, curmsg->desc, curmsg->index);
1578 computeStat(CStat::E_CALL_FAILED);
1579 computeStat(CStat::E_FAILED_TIMEOUT_ON_RECV);
1580 if (default_behaviors & DEFAULT_BEHAVIOR_BYE) {
1581 return (abortCall(true));
1582 } else {
1583 delete this;
1584 return false;
1585 }
1586 }
1587 WARNING("Call-Id: %s, receive timeout on message %s:%d, jumping to label %d",
1588 id, curmsg->desc, curmsg->index, curmsg->on_timeout);
1589 /* FIXME: We should do something like set index here, but it probably
1590 * does not matter too much as only nops are allowed in the init stanza. */
1591 msg_index = curmsg->on_timeout;
1592 recv_timeout = 0;
1593 if (msg_index < (int)call_scenario->messages.size()) return true;
1594 // special case - the label points to the end - finish the call
1595 computeStat(CStat::E_CALL_FAILED);
1596 computeStat(CStat::E_FAILED_TIMEOUT_ON_RECV);
1597 if (default_behaviors & DEFAULT_BEHAVIOR_BYE) {
1598 return (abortCall(true));
1599 } else {
1600 delete this;
1601 return false;
1602 }
1603 } else if (curmsg->timeout || defl_recv_timeout) {
1604 if (curmsg->timeout)
1605 // If timeout is specified on message receive, use it
1606 recv_timeout = getmilliseconds() + curmsg->timeout;
1607 else
1608 // Else use the default timeout if specified
1609 recv_timeout = getmilliseconds() + defl_recv_timeout;
1610 return true;
1611 } else {
1612 /* We are going to wait forever. */
1613 setPaused();
1614 }
1615 } else {
1616 WARNING("Unknown message type at %s:%d: %d", curmsg->desc, curmsg->index, curmsg->M_type);
1617 }
1618 return true;
1619 }
1620
run()1621 bool call::run()
1622 {
1623 bool bInviteTransaction = false;
1624
1625 assert(running);
1626
1627 if (zombie) {
1628 delete this;
1629 return false;
1630 }
1631
1632 getmilliseconds();
1633
1634 message *curmsg;
1635 if (initCall) {
1636 if(msg_index >= (int)call_scenario->initmessages.size()) {
1637 ERROR("Scenario initialization overrun for call %s (%p) (index = %d)\n", id, _RCAST(void*, this), msg_index);
1638 }
1639 curmsg = call_scenario->initmessages[msg_index];
1640 } else {
1641 if(msg_index >= (int)call_scenario->messages.size()) {
1642 ERROR("Scenario overrun for call %s (%p) (index = %d)\n", id, _RCAST(void*, this), msg_index);
1643 }
1644 curmsg = call_scenario->messages[msg_index];
1645 }
1646
1647 callDebug("Processing message %d of type %d for call %s at %lu.\n", msg_index, curmsg->M_type, id, clock_tick);
1648
1649 if (curmsg->condexec != -1) {
1650 bool exec = M_callVariableTable->getVar(curmsg->condexec)->isSet();
1651 if (curmsg->condexec_inverse) {
1652 exec = !exec;
1653 }
1654 if (!exec) {
1655 callDebug("Conditional variable %s %s set, so skipping message %d.\n", call_scenario->allocVars->getName(curmsg->condexec), curmsg->condexec_inverse ? "" : "not", msg_index);
1656 return next();
1657 }
1658 }
1659
1660 /* Manages retransmissions or delete if max retrans reached */
1661 if(next_retrans && (next_retrans < clock_tick)) {
1662 nb_retrans++;
1663
1664 if ( (0 == strncmp (last_send_msg, "INVITE", 6)) ) {
1665 bInviteTransaction = true;
1666 }
1667
1668 int rtAllowed = min(bInviteTransaction ? max_invite_retrans : max_non_invite_retrans, max_udp_retrans);
1669
1670 callDebug("Retransmisison required (%d retransmissions, max %d)\n", nb_retrans, rtAllowed);
1671
1672 if(nb_retrans > rtAllowed) {
1673 call_scenario->messages[last_send_index] -> nb_timeout ++;
1674 if (call_scenario->messages[last_send_index]->on_timeout >= 0) { // action on timeout
1675 WARNING("Call-Id: %s, timeout on max UDP retrans for message %d, jumping to label %d ",
1676 id, msg_index, call_scenario->messages[last_send_index]->on_timeout);
1677 msg_index = call_scenario->messages[last_send_index]->on_timeout;
1678 next_retrans = 0;
1679 recv_timeout = 0;
1680 if (msg_index < (int)call_scenario->messages.size()) {
1681 return true;
1682 }
1683
1684 // here if asked to go to the last label delete the call
1685 computeStat(CStat::E_CALL_FAILED);
1686 computeStat(CStat::E_FAILED_MAX_UDP_RETRANS);
1687 if (default_behaviors & DEFAULT_BEHAVIOR_BYE) {
1688 // Abort the call by sending proper SIP message
1689 return(abortCall(true));
1690 } else {
1691 // Just delete existing call
1692 delete this;
1693 return false;
1694 }
1695 }
1696 computeStat(CStat::E_CALL_FAILED);
1697 computeStat(CStat::E_FAILED_MAX_UDP_RETRANS);
1698 if (default_behaviors & DEFAULT_BEHAVIOR_BYE) {
1699 // Abort the call by sending proper SIP message
1700 WARNING("Aborting call on UDP retransmission timeout for Call-ID '%s'", id);
1701 return(abortCall(true));
1702 } else {
1703 // Just delete existing call
1704 delete this;
1705 return false;
1706 }
1707 } else {
1708 nb_last_delay *= 2;
1709 if (global_t2 < nb_last_delay) {
1710 if (!bInviteTransaction) {
1711 nb_last_delay = global_t2;
1712 }
1713 }
1714 if(send_raw(last_send_msg, last_send_index, last_send_len) < -1) {
1715 return false;
1716 }
1717 call_scenario->messages[last_send_index] -> nb_sent_retrans++;
1718 computeStat(CStat::E_RETRANSMISSION);
1719 next_retrans = clock_tick + nb_last_delay;
1720 }
1721 }
1722
1723 if(paused_until) {
1724 /* Process a pending pause instruction until delay expiration */
1725 if(paused_until > clock_tick) {
1726 callDebug("Call is paused until %d (now %ld).\n", paused_until, clock_tick);
1727 setPaused();
1728 callDebug("Running: %d (wake %d).\n", running, wake());
1729 return true;
1730 }
1731 /* Our pause is over. */
1732 callDebug("Pause complete, waking up.\n");
1733 paused_until = 0;
1734 return next();
1735 }
1736 return executeMessage(curmsg);
1737 }
1738
1739 const char *default_message_names[] = {
1740 "3pcc_abort",
1741 "ack",
1742 "ack2",
1743 "bye",
1744 "cancel",
1745 "200",
1746 };
1747 const char *default_message_strings[] = {
1748 /* 3pcc_abort */
1749 "call-id: [call_id]\ninternal-cmd: abort_call\n\n",
1750 /* ack */
1751 "ACK [last_Request_URI] SIP/2.0\n"
1752 "[last_Via]\n"
1753 "[last_From]\n"
1754 "[last_To]\n"
1755 "Call-ID: [call_id]\n"
1756 "CSeq: [last_cseq_number] ACK\n"
1757 "Contact: <sip:sipp@[local_ip]:[local_port];transport=[transport]>\n"
1758 "Max-Forwards: 70\n"
1759 "Subject: Performance Test\n"
1760 "Content-Length: 0\n\n",
1761 /* ack2, the only difference is Via, I don't quite know why. */
1762 "ACK [last_Request_URI] SIP/2.0\n"
1763 "Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
1764 "[last_From]\n"
1765 "[last_To]\n"
1766 "Call-ID: [call_id]\n"
1767 "CSeq: [last_cseq_number] ACK\n"
1768 "Contact: <sip:sipp@[local_ip]:[local_port];transport=[transport]>\n"
1769 "Max-Forwards: 70\n"
1770 "Subject: Performance Test\n"
1771 "Content-Length: 0\n\n",
1772 /* bye */
1773 "BYE [last_Request_URI] SIP/2.0\n"
1774 "Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]\n"
1775 "[last_From]\n"
1776 "[last_To]\n"
1777 "Call-ID: [call_id]\n"
1778 "CSeq: [last_cseq_number+1] BYE\n"
1779 "Max-Forwards: 70\n"
1780 "Contact: <sip:sipp@[local_ip]:[local_port];transport=[transport]>\n"
1781 "Content-Length: 0\n\n",
1782 /* cancel */
1783 "CANCEL [last_Request_URI] SIP/2.0\n"
1784 "[last_Via]\n"
1785 "[last_From]\n"
1786 "[last_To]\n"
1787 "Call-ID: [call_id]\n"
1788 "CSeq: [last_cseq_number] CANCEL\n"
1789 "Max-Forwards: 70\n"
1790 "Contact: <sip:sipp@[local_ip]:[local_port];transport=[transport]>\n"
1791 "Content-Length: 0\n\n",
1792 /* 200 */
1793 "SIP/2.0 200 OK\n"
1794 "[last_Via:]\n"
1795 "[last_From:]\n"
1796 "[last_To:]\n"
1797 "[last_Call-ID:]\n"
1798 "[last_CSeq:]\n"
1799 "Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"
1800 "Content-Length: 0\n\n"
1801 };
1802
1803 SendingMessage **default_messages;
1804
init_default_messages()1805 void init_default_messages()
1806 {
1807 int messages = sizeof(default_message_strings)/sizeof(default_message_strings[0]);
1808 default_messages = new SendingMessage* [messages];
1809 for (int i = 0; i < messages; i++) {
1810 default_messages[i] = new SendingMessage(main_scenario, const_cast<char*>(default_message_strings[i]));
1811 }
1812 }
1813
free_default_messages()1814 void free_default_messages()
1815 {
1816 int messages = sizeof(default_message_strings)/sizeof(default_message_strings[0]);
1817 if (!default_messages) {
1818 return;
1819 }
1820 for (int i = 0; i < messages; i++) {
1821 delete default_messages[i];
1822 }
1823 delete [] default_messages;
1824 }
1825
get_default_message(const char * which)1826 SendingMessage *get_default_message(const char *which)
1827 {
1828 int messages = sizeof(default_message_names)/sizeof(default_message_names[0]);
1829 for (int i = 0; i < messages; i++) {
1830 if (!strcmp(which, default_message_names[i])) {
1831 return default_messages[i];
1832 }
1833 }
1834 ERROR("Internal Error: Unknown default message: %s!", which);
1835 }
1836
set_default_message(const char * which,char * msg)1837 void set_default_message(const char *which, char *msg)
1838 {
1839 int messages = sizeof(default_message_names)/sizeof(default_message_names[0]);
1840 for (int i = 0; i < messages; i++) {
1841 if (!strcmp(which, default_message_names[i])) {
1842 default_message_strings[i] = msg;
1843 return;
1844 }
1845 }
1846 ERROR("Internal Error: Unknown default message: %s!", which);
1847 }
1848
process_unexpected(char * msg)1849 bool call::process_unexpected(char * msg)
1850 {
1851 char buffer[MAX_HEADER_LEN];
1852 char *desc = buffer;
1853 int res = 0;
1854
1855 message *curmsg = call_scenario->messages[msg_index];
1856
1857 curmsg->nb_unexp++;
1858
1859 if (default_behaviors & DEFAULT_BEHAVIOR_ABORTUNEXP) {
1860 desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "Aborting ");
1861 } else {
1862 desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "Continuing ");
1863 }
1864 desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "call on unexpected message for Call-Id '%s': ", id);
1865
1866 if (curmsg -> M_type == MSG_TYPE_RECV) {
1867 if (curmsg -> recv_request) {
1868 desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting '%s' ", curmsg -> recv_request);
1869 } else {
1870 desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting '%d' ", curmsg -> recv_response);
1871 }
1872 } else if (curmsg -> M_type == MSG_TYPE_SEND) {
1873 desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while sending ");
1874 } else if (curmsg -> M_type == MSG_TYPE_PAUSE) {
1875 desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while pausing ");
1876 } else if (curmsg -> M_type == MSG_TYPE_SENDCMD) {
1877 desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while sending command ");
1878 } else if (curmsg -> M_type == MSG_TYPE_RECVCMD) {
1879 desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting command ");
1880 } else {
1881 desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while in message type %d ", curmsg->M_type);
1882 }
1883 snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "(index %d)", msg_index);
1884
1885 WARNING("%s, received '%s'", buffer, msg);
1886
1887 TRACE_MSG("-----------------------------------------------\n"
1888 "Unexpected %s message received:\n\n%s\n",
1889 TRANSPORT_TO_STRING(transport),
1890 msg);
1891
1892 callDebug("Unexpected %s message received (index %d, hash %lu):\n\n%s\n",
1893 TRANSPORT_TO_STRING(transport), msg_index, hash(msg), msg);
1894
1895 if (get_reply_code(msg)) {
1896 this->call_scenario->stats->error_codes.push_back(get_reply_code(msg));
1897 }
1898
1899 if (default_behaviors & DEFAULT_BEHAVIOR_ABORTUNEXP) {
1900 // if twin socket call => reset the other part here
1901 if (twinSippSocket && (msg_index > 0)) {
1902 res = sendCmdBuffer(createSendingMessage(get_default_message("3pcc_abort"), -1));
1903 if (res < 0) {
1904 WARNING("sendCmdBuffer returned %d", res);
1905 return false;
1906 }
1907 }
1908
1909 // usage of last_ keywords => for call aborting
1910 realloc_ptr = (char *) realloc(last_recv_msg, strlen(msg) + 1);
1911 if (realloc_ptr) {
1912 last_recv_msg = realloc_ptr;
1913 } else {
1914 free(last_recv_msg);
1915 ERROR("Out of memory!");
1916 return false;
1917 }
1918
1919 strcpy(last_recv_msg, msg);
1920
1921 computeStat(CStat::E_CALL_FAILED);
1922 computeStat(CStat::E_FAILED_UNEXPECTED_MSG);
1923 if (default_behaviors & DEFAULT_BEHAVIOR_BYE) {
1924 return (abortCall(true));
1925 } else {
1926 delete this;
1927 return false;
1928 }
1929 } else {
1930 // Do not abort call nor send anything in reply if default behavior is disabled
1931 return false;
1932 }
1933 }
1934
abort()1935 void call::abort()
1936 {
1937 WARNING("Aborted call with Call-ID '%s'", id);
1938 abortCall(false);
1939 }
1940
abortCall(bool writeLog)1941 bool call::abortCall(bool writeLog)
1942 {
1943 int is_inv;
1944
1945 char * src_recv = NULL ;
1946
1947 callDebug("Aborting call %s (index %d).\n", id, msg_index);
1948
1949 if (last_send_msg != NULL) {
1950 is_inv = !strncmp(last_send_msg, "INVITE", 6);
1951 } else {
1952 is_inv = false;
1953 }
1954 if ((creationMode != MODE_SERVER) && (msg_index > 0)) {
1955 if ((call_established == false) && (is_inv)) {
1956 src_recv = last_recv_msg ;
1957
1958 // Answer unexpected errors (4XX, 5XX and beyond) with an ACK
1959 // Contributed by F. Tarek Rogers
1960 if((src_recv) && (get_reply_code(src_recv) >= 400)) {
1961 sendBuffer(createSendingMessage(get_default_message("ack"), -2));
1962 } else if (src_recv) {
1963 /* Call is not established and the reply is not a 4XX, 5XX */
1964 /* And we already received a message. */
1965 if (ack_is_pending == true) {
1966 /* If an ACK is expected from the other side, send it
1967 * and send a BYE afterwards */
1968 ack_is_pending = false;
1969 /* Send an ACK */
1970 sendBuffer(createSendingMessage(get_default_message("ack"), -1));
1971
1972 /* Send the BYE */
1973 sendBuffer(createSendingMessage(get_default_message("bye"), -1));
1974 } else {
1975 /* Send a CANCEL */
1976 sendBuffer(createSendingMessage(get_default_message("cancel"), -1));
1977 }
1978 } else {
1979 /* Call is not established and the reply is not a 4XX, 5XX */
1980 /* and we didn't received any message. This is the case when */
1981 /* we are aborting after having send an INVITE and not received */
1982 /* any answer. */
1983 /* Do nothing ! */
1984 }
1985 } else if (last_recv_msg) {
1986 /* The call may not be established, if we haven't yet received a message,
1987 * because the earlier check depends on the first message being an INVITE
1988 * (although it could be something like a message message, therefore we
1989 * check that we received a message. */
1990 sendBuffer(createSendingMessage(get_default_message("bye"), -1));
1991 }
1992 }
1993
1994 if (writeLog && useCallDebugf) {
1995 TRACE_CALLDEBUG ("-------------------------------------------------------------------------------\n");
1996 TRACE_CALLDEBUG ("Call debugging information for call %s:\n", id);
1997 TRACE_CALLDEBUG("%s", debugBuffer);
1998 }
1999
2000 stopListening();
2001 if (deadcall_wait && !initCall) {
2002 char reason[100];
2003 sprintf(reason, "aborted at index %d", msg_index);
2004 new deadcall(id, reason);
2005 }
2006 delete this;
2007
2008 return false;
2009 }
2010
rejectCall()2011 bool call::rejectCall()
2012 {
2013 computeStat(CStat::E_CALL_FAILED);
2014 computeStat(CStat::E_FAILED_CALL_REJECTED);
2015 delete this;
2016 return false;
2017 }
2018
2019
sendCmdMessage(message * curmsg)2020 int call::sendCmdMessage(message *curmsg)
2021 {
2022 char * dest;
2023 char delimitor[2];
2024 delimitor[0]=27;
2025 delimitor[1]=0;
2026
2027 /* 3pcc extended mode */
2028 char * peer_dest;
2029 struct sipp_socket **peer_socket;
2030
2031 if(curmsg -> M_sendCmdData) {
2032 // WARNING("---PREPARING_TWIN_CMD---%s---", scenario[index] -> M_sendCmdData);
2033 dest = createSendingMessage(curmsg -> M_sendCmdData, -1);
2034 strcat(dest, delimitor);
2035 //WARNING("---SEND_TWIN_CMD---%s---", dest);
2036
2037 int rc;
2038
2039 /* 3pcc extended mode */
2040 peer_dest = curmsg->peer_dest;
2041 if(peer_dest) {
2042 peer_socket = get_peer_socket(peer_dest);
2043 rc = write_socket(*peer_socket, dest, strlen(dest), WS_BUFFER, &call_peer);
2044 } else {
2045 rc = write_socket(twinSippSocket, dest, strlen(dest), WS_BUFFER, &call_peer);
2046 }
2047 if(rc < 0) {
2048 computeStat(CStat::E_CALL_FAILED);
2049 computeStat(CStat::E_FAILED_CMD_NOT_SENT);
2050 delete this;
2051 return(-1);
2052 }
2053
2054 return(0);
2055 } else
2056 return(-1);
2057 }
2058
2059
sendCmdBuffer(char * cmd)2060 int call::sendCmdBuffer(char* cmd)
2061 {
2062 char * dest;
2063 char delimitor[2];
2064 int rc;
2065
2066 delimitor[0]=27;
2067 delimitor[1]=0;
2068
2069 dest = cmd ;
2070
2071 strcat(dest, delimitor);
2072
2073 rc = write_socket(twinSippSocket, dest, strlen(dest), WS_BUFFER, &twinSippSocket->ss_remote_sockaddr);
2074 if(rc < 0) {
2075 computeStat(CStat::E_CALL_FAILED);
2076 computeStat(CStat::E_FAILED_CMD_NOT_SENT);
2077 delete this;
2078 return(-1);
2079 }
2080
2081 return(0);
2082 }
2083
2084
createSendingMessage(SendingMessage * src,int P_index,int * msgLen)2085 char* call::createSendingMessage(SendingMessage *src, int P_index, int *msgLen)
2086 {
2087 static char msg_buffer[SIPP_MAX_MSG_SIZE+2];
2088 return createSendingMessage(src, P_index, msg_buffer, sizeof(msg_buffer), msgLen);
2089 }
2090
createSendingMessage(SendingMessage * src,int P_index,char * msg_buffer,int buf_len,int * msgLen)2091 char* call::createSendingMessage(SendingMessage *src, int P_index, char *msg_buffer, int buf_len, int *msgLen)
2092 {
2093 char * length_marker = NULL;
2094 char * auth_marker = NULL;
2095 MessageComponent *auth_comp = NULL;
2096 bool auth_comp_allocated = false;
2097 int len_offset = 0;
2098 char *dest = msg_buffer;
2099 bool suppresscrlf = false;
2100
2101 *dest = '\0';
2102
2103 for (int i = 0; i < src->numComponents(); i++) {
2104 MessageComponent *comp = src->getComponent(i);
2105 int left = buf_len - (dest - msg_buffer);
2106 switch(comp->type) {
2107 case E_Message_Literal:
2108 if (suppresscrlf) {
2109 char *ptr = comp->literal;
2110 while (isspace(*ptr)) ptr++;
2111 dest += snprintf(dest, left, "%s", ptr);
2112 suppresscrlf = false;
2113 } else {
2114 memcpy(dest, comp->literal, comp->literalLen);
2115 dest += comp->literalLen;
2116 *dest = '\0';
2117 }
2118 break;
2119 case E_Message_Remote_IP:
2120 dest += snprintf(dest, left, "%s", remote_ip_escaped);
2121 break;
2122 case E_Message_Remote_Host:
2123 dest += snprintf(dest, left, "%s", remote_host);
2124 break;
2125 case E_Message_Remote_Port:
2126 dest += snprintf(dest, left, "%d", remote_port + comp->offset);
2127 break;
2128 case E_Message_Local_IP:
2129 dest += snprintf(dest, left, "%s", local_ip_escaped);
2130 break;
2131 case E_Message_Local_Port:
2132 int port;
2133 if((transport == T_UDP) && (multisocket) && (sendMode != MODE_SERVER)) {
2134 port = call_port;
2135 } else {
2136 port = local_port;
2137 }
2138 dest += snprintf(dest, left, "%d", port + comp->offset);
2139 break;
2140 case E_Message_Transport:
2141 dest += snprintf(dest, left, "%s", TRANSPORT_TO_STRING(transport));
2142 break;
2143 case E_Message_Local_IP_Type:
2144 dest += snprintf(dest, left, "%s", (local_ip_is_ipv6 ? "6" : "4"));
2145 break;
2146 case E_Message_Server_IP: {
2147 /* We should do this conversion once per socket creation, rather than
2148 * repeating it every single time. */
2149 struct sockaddr_storage server_sockaddr;
2150
2151 sipp_socklen_t len = sizeof(server_sockaddr);
2152 getsockname(call_socket->ss_fd,
2153 (sockaddr *)(void *)&server_sockaddr, &len);
2154
2155 char address[INET6_ADDRSTRLEN];
2156 if (getnameinfo(_RCAST(sockaddr*, &server_sockaddr), len, address, sizeof(address),
2157 NULL, 0, NI_NUMERICHOST) < 0) {
2158 ERROR_NO("Unable to get socket name information");
2159 }
2160
2161 dest += snprintf(dest, left, "%s", address);
2162 }
2163 break;
2164 case E_Message_Media_IP:
2165 dest += snprintf(dest, left, "%s", media_ip_escaped);
2166 break;
2167 case E_Message_Media_Port:
2168 case E_Message_Auto_Media_Port: {
2169 int port = media_port + comp->offset;
2170 if (comp->type == E_Message_Auto_Media_Port) {
2171 port = media_port + (4 * (number - 1)) % 10000 + comp->offset;
2172 }
2173 #ifdef PCAPPLAY
2174 char *begin = dest;
2175 while (begin > msg_buffer) {
2176 if (*begin == '\n') {
2177 break;
2178 }
2179 begin--;
2180 }
2181 if (begin == msg_buffer) {
2182 ERROR("Can not find beginning of a line for the media port!\n");
2183 }
2184 play_args_t *play_args = NULL;
2185 if (strstr(begin, "audio")) {
2186 play_args = &play_args_a;
2187 } else if (strstr(begin, "image")) {
2188 play_args = &play_args_i;
2189 } else if (strstr(begin, "video")) {
2190 play_args = &play_args_v;
2191 } else {
2192 ERROR("media_port keyword with no audio or video on the current line (%s)", begin);
2193 }
2194 if (media_ip_is_ipv6) {
2195 (_RCAST(struct sockaddr_in6 *, &(play_args->from)))->sin6_port = htons(port);
2196 } else {
2197 (_RCAST(struct sockaddr_in *, &(play_args->from)))->sin_port = htons(port);
2198 }
2199 #endif
2200 dest += sprintf(dest, "%u", port);
2201 break;
2202 }
2203 #ifdef RTP_STREAM
2204 case E_Message_RTPStream_Audio_Port:
2205 {
2206 int temp_audio_port= rtpstream_get_audioport (&rtpstream_callinfo);
2207 if (!temp_audio_port) {
2208 /* Make this a warning instead? */
2209 ERROR("cannot assign a free audio port to this call - using 0 for [rtpstream_audio_port]");
2210 }
2211 dest += snprintf(dest, left, "%d",temp_audio_port);
2212 }
2213 break;
2214 case E_Message_RTPStream_Video_Port:
2215 {
2216 int temp_video_port= rtpstream_get_videoport (&rtpstream_callinfo);
2217 if (!temp_video_port) {
2218 /* Make this a warning instead? */
2219 ERROR("cannot assign a free video port to this call - using 0 for [rtpstream_video_port]");
2220 }
2221 dest += snprintf(dest, left, "%d",temp_video_port);
2222 }
2223 break;
2224 #endif
2225 case E_Message_Media_IP_Type:
2226 dest += snprintf(dest, left, "%s", (media_ip_is_ipv6 ? "6" : "4"));
2227 break;
2228 case E_Message_Call_Number:
2229 dest += snprintf(dest, left, "%u", number);
2230 break;
2231 case E_Message_DynamicId:
2232 dest += snprintf(dest, left, "%u", call::dynamicId);
2233 // increment at each request
2234 dynamicId += stepDynamicId;
2235 if ( this->dynamicId > maxDynamicId ) {
2236 call::dynamicId = call::startDynamicId;
2237 } ;
2238 break;
2239 case E_Message_Call_ID:
2240 dest += snprintf(dest, left, "%s", id);
2241 break;
2242 case E_Message_CSEQ:
2243 dest += snprintf(dest, left, "%u", cseq + comp->offset);
2244 break;
2245 case E_Message_PID:
2246 dest += snprintf(dest, left, "%d", pid);
2247 break;
2248 case E_Message_Service:
2249 dest += snprintf(dest, left, "%s", service);
2250 break;
2251 case E_Message_Branch:
2252 /* Branch is magic cookie + call number + message index in scenario */
2253 if(P_index == -2) {
2254 dest += snprintf(dest, left, "z9hG4bK-%u-%u-%d", pid, number, msg_index-1 + comp->offset);
2255 } else {
2256 dest += snprintf(dest, left, "z9hG4bK-%u-%u-%d", pid, number, P_index + comp->offset);
2257 }
2258 break;
2259 case E_Message_Index:
2260 dest += snprintf(dest, left, "%d", P_index);
2261 break;
2262 case E_Message_Next_Url:
2263 if (next_req_url) {
2264 dest += sprintf(dest, "%s", next_req_url);
2265 }
2266 break;
2267 case E_Message_Len:
2268 length_marker = dest;
2269 dest += snprintf(dest, left, " ");
2270 len_offset = comp->offset;
2271 break;
2272 case E_Message_Authentication:
2273 if (auth_marker) {
2274 ERROR("Only one [authentication] keyword is currently supported!\n");
2275 }
2276 auth_marker = dest;
2277 dest += snprintf(dest, left, "[authentication place holder]");
2278 auth_comp = comp;
2279 break;
2280 case E_Message_Peer_Tag_Param:
2281 if(peer_tag) {
2282 dest += snprintf(dest, left, ";tag=%s", peer_tag);
2283 }
2284 break;
2285 case E_Message_Routes:
2286 if (dialog_route_set) {
2287 dest += sprintf(dest, "Route: %s", dialog_route_set);
2288 } else if (*(dest - 1) == '\n') {
2289 suppresscrlf = true;
2290 }
2291 break;
2292 case E_Message_ClockTick:
2293 dest += snprintf(dest, left, "%lu", clock_tick);
2294 break;
2295 case E_Message_Timestamp:
2296 struct timeval currentTime;
2297 gettimeofday(¤tTime, NULL);
2298 dest += snprintf(dest, left, "%s", CStat::formatTime(¤tTime));
2299 break;
2300 case E_Message_Date:
2301 char buf[256];
2302 time_t t;
2303 struct tm *tm;
2304
2305 t = time(NULL);
2306 tm = gmtime(&t);
2307
2308 strftime(buf, 256, "%a, %d %b %Y %T %Z", tm);
2309 dest += snprintf(dest, left, "%s", buf);
2310 break;
2311 case E_Message_Users:
2312 dest += snprintf(dest, left, "%d", users);
2313 break;
2314 case E_Message_UserID:
2315 dest += snprintf(dest, left, "%d", userId);
2316 break;
2317 case E_Message_SippVersion:
2318 /* Drop the initial "v" from the VERSION string for legacy reasons. */
2319 dest += snprintf(dest, left, "%s", (const char*)VERSION + 1);
2320 break;
2321 case E_Message_Variable: {
2322 int varId = comp->varId;
2323 CCallVariable *var = M_callVariableTable->getVar(varId);
2324 if(var->isSet()) {
2325 if (var->isRegExp()) {
2326 dest += sprintf(dest, "%s", var->getMatchingValue());
2327 } else if (var->isDouble()) {
2328 dest += sprintf(dest, "%lf", var->getDouble());
2329 } else if (var->isString()) {
2330 dest += sprintf(dest, "%s", var->getString());
2331 } else if (var->isBool()) {
2332 dest += sprintf(dest, "true");
2333 }
2334 } else if (var->isBool()) {
2335 dest += sprintf(dest, "false");
2336 }
2337 if (*(dest - 1) == '\n') {
2338 suppresscrlf = true;
2339 }
2340 break;
2341 }
2342 case E_Message_Fill: {
2343 int varId = comp->varId;
2344 int length = (int) M_callVariableTable->getVar(varId)->getDouble();
2345 if (length < 0) {
2346 length = 0;
2347 }
2348 char *filltext = comp->literal;
2349 int filllen = strlen(filltext);
2350 if (filllen == 0) {
2351 ERROR("Internal error: [fill] keyword has zero-length text.");
2352 }
2353 for (int i = 0, j = 0; i < length; i++, j++) {
2354 *dest++ = filltext[j % filllen];
2355 }
2356 *dest = '\0';
2357 break;
2358 }
2359 case E_Message_File: {
2360 char buffer[MAX_HEADER_LEN];
2361 createSendingMessage(comp->comp_param.filename, -2, buffer, sizeof(buffer));
2362 FILE *f = fopen(buffer, "r");
2363 if (!f) {
2364 ERROR("Could not open '%s': %s\n", buffer, strerror(errno));
2365 }
2366 int ret;
2367 while ((ret = fread(dest, 1, left, f)) > 0) {
2368 left -= ret;
2369 dest += ret;
2370 }
2371 if (ret < 0) {
2372 ERROR("Error reading '%s': %s\n", buffer, strerror(errno));
2373 }
2374 fclose(f);
2375 break;
2376 }
2377 case E_Message_Injection: {
2378 char *orig_dest = dest;
2379 getFieldFromInputFile(comp->comp_param.field_param.filename, comp->comp_param.field_param.field, comp->comp_param.field_param.line, dest);
2380 /* We are injecting an authentication line. */
2381 if (char *tmp = strstr(orig_dest, "[authentication")) {
2382 if (auth_marker) {
2383 ERROR("Only one [authentication] keyword is currently supported!\n");
2384 }
2385 auth_marker = tmp;
2386 auth_comp = (struct MessageComponent *)calloc(1, sizeof(struct MessageComponent));
2387 if (!auth_comp) {
2388 ERROR("Out of memory!");
2389 }
2390 auth_comp_allocated = true;
2391
2392 tmp = strchr(auth_marker, ']');
2393 char c = *tmp;
2394 *tmp = '\0';
2395 SendingMessage::parseAuthenticationKeyword(call_scenario, auth_comp, auth_marker);
2396 *tmp = c;
2397 }
2398 if (*(dest - 1) == '\n') {
2399 suppresscrlf = true;
2400 }
2401 break;
2402 }
2403 case E_Message_Last_Header: {
2404 char * last_header = get_last_header(comp->literal);
2405 if(last_header) {
2406 dest += sprintf(dest, "%s", last_header);
2407 }
2408 if (*(dest - 1) == '\n') {
2409 suppresscrlf = true;
2410 }
2411 break;
2412 }
2413 case E_Message_Custom: {
2414 dest += comp->comp_param.fxn(this, comp, dest, left);
2415 break;
2416 }
2417 case E_Message_Last_Message:
2418 if(last_recv_msg && strlen(last_recv_msg)) {
2419 dest += sprintf(dest, "%s", last_recv_msg);
2420 }
2421 break;
2422 case E_Message_Last_Request_URI: {
2423 char * last_request_uri = get_last_request_uri();
2424 dest += sprintf(dest, "%s", last_request_uri);
2425 free(last_request_uri);
2426 break;
2427 }
2428 case E_Message_Last_CSeq_Number: {
2429 int last_cseq = 0;
2430
2431 char *last_header = get_last_header("CSeq:");
2432 if(last_header) {
2433 last_header += 5;
2434 /* Extract the integer value of the field */
2435 while(isspace(*last_header)) last_header++;
2436 sscanf(last_header,"%d", &last_cseq);
2437 }
2438 dest += sprintf(dest, "%d", last_cseq + comp->offset);
2439 break;
2440 }
2441 case E_Message_TDM_Map:
2442 if (!use_tdmmap)
2443 ERROR("[tdmmap] keyword without -tdmmap parameter on command line");
2444 dest += snprintf(dest, left, "%d.%d.%d/%d",
2445 tdm_map_x+(int((tdm_map_number)/((tdm_map_b+1)*(tdm_map_c+1))))%(tdm_map_a+1),
2446 tdm_map_h,
2447 tdm_map_y+(int((tdm_map_number)/(tdm_map_c+1)))%(tdm_map_b+1),
2448 tdm_map_z+(tdm_map_number)%(tdm_map_c+1)
2449 );
2450 break;
2451 }
2452 }
2453 /* Need the body for length and auth-int calculation */
2454 char *body;
2455 const char *auth_body = NULL;
2456 if (length_marker || auth_marker) {
2457 body = strstr(msg_buffer, "\r\n\r\n");
2458 if (body) {
2459 auth_body = body;
2460 auth_body += strlen("\r\n\r\n");
2461 }
2462 }
2463 if (!auth_body) {
2464 auth_body = "";
2465 }
2466
2467 /* Fix up the length. */
2468 if (length_marker) {
2469 if (auth_marker > body) {
2470 ERROR("The authentication keyword should appear in the message header, not the body!");
2471 }
2472
2473 if (body && dest - body > 4 && dest - body < 100004) {
2474 char tmp = length_marker[5];
2475 sprintf(length_marker, "%5u", (unsigned)(dest - body - 4 + len_offset));
2476 length_marker[5] = tmp;
2477 } else {
2478 // Other cases: Content-Length is 0
2479 sprintf(length_marker, " 0\r\n\r\n");
2480 }
2481 }
2482
2483 if (msgLen) {
2484 *msgLen = dest - msg_buffer;
2485 }
2486
2487 /*
2488 * The authentication substitution must be done outside the above
2489 * loop because auth-int will use the body (which must have already
2490 * been keyword substituted) to build the md5 hash
2491 */
2492 if (auth_marker) {
2493 if (!dialog_authentication) {
2494 ERROR("Authentication keyword without dialog_authentication!");
2495 }
2496
2497 int auth_marker_len;
2498 char * tmp;
2499 int authlen;
2500
2501 auth_marker_len = (strchr(auth_marker, ']') + 1) - auth_marker;
2502
2503 /* Need the Method name from the CSeq of the Challenge */
2504 char method[MAX_HEADER_LEN];
2505 tmp = get_last_header("CSeq:");
2506 if(!tmp) {
2507 ERROR("Could not extract method from cseq of challenge");
2508 }
2509 tmp += 5;
2510 while(isspace(*tmp) || isdigit(*tmp)) tmp++;
2511 sscanf(tmp,"%s", method);
2512
2513 /* Determine the type of credentials. */
2514 char result[MAX_HEADER_LEN];
2515 if (dialog_challenge_type == 401) {
2516 /* Registrars use Authorization */
2517 authlen = sprintf(result, "Authorization: ");
2518 } else {
2519 /* Proxies use Proxy-Authorization */
2520 authlen = sprintf(result, "Proxy-Authorization: ");
2521 }
2522
2523 /* Build the auth credenticals */
2524 char uri[MAX_HEADER_LEN];
2525 sprintf (uri, "%s:%d", remote_ip, remote_port);
2526 /* These cause this function to not be reentrant. */
2527 static char my_auth_user[MAX_HEADER_LEN + 2];
2528 static char my_auth_pass[MAX_HEADER_LEN + 2];
2529 static char my_aka_OP[MAX_HEADER_LEN + 2];
2530 static char my_aka_AMF[MAX_HEADER_LEN + 2];
2531 static char my_aka_K[MAX_HEADER_LEN + 2];
2532
2533 createSendingMessage(auth_comp->comp_param.auth_param.auth_user, -2, my_auth_user, sizeof(my_auth_user));
2534 createSendingMessage(auth_comp->comp_param.auth_param.auth_pass, -2, my_auth_pass, sizeof(my_auth_pass));
2535 createSendingMessage(auth_comp->comp_param.auth_param.aka_K, -2, my_aka_K, sizeof(my_aka_K));
2536 createSendingMessage(auth_comp->comp_param.auth_param.aka_AMF, -2, my_aka_AMF, sizeof(my_aka_AMF));
2537 createSendingMessage(auth_comp->comp_param.auth_param.aka_OP, -2, my_aka_OP, sizeof(my_aka_OP));
2538
2539 if (createAuthHeader(my_auth_user, my_auth_pass, method, uri, auth_body, dialog_authentication,
2540 my_aka_OP, my_aka_AMF, my_aka_K, result + authlen) == 0) {
2541 ERROR("%s", result + authlen);
2542 }
2543 authlen = strlen(result);
2544
2545 /* Shift the end of the message to its rightful place. */
2546 memmove(auth_marker + authlen, auth_marker + auth_marker_len, strlen(auth_marker + auth_marker_len) + 1);
2547 /* Copy our result into the hole. */
2548 memcpy(auth_marker, result, authlen);
2549 if (msgLen) {
2550 *msgLen += (authlen - auth_marker_len);
2551 }
2552 }
2553
2554 if (auth_comp_allocated) {
2555 SendingMessage::freeMessageComponent(auth_comp);
2556 }
2557
2558 return msg_buffer;
2559 }
2560
process_twinSippCom(char * msg)2561 bool call::process_twinSippCom(char * msg)
2562 {
2563 int search_index;
2564 bool found = false;
2565 T_ActionResult actionResult;
2566
2567 callDebug("Processing incoming command for call-ID %s:\n%s\n\n", id, msg);
2568
2569 setRunning();
2570
2571 if (checkInternalCmd(msg) == false) {
2572
2573 for(search_index = msg_index;
2574 search_index < (int)call_scenario->messages.size();
2575 search_index++) {
2576 if(call_scenario->messages[search_index] -> M_type != MSG_TYPE_RECVCMD) {
2577 if ((call_scenario->messages[search_index] -> optional) ||
2578 (call_scenario->messages[search_index] -> M_type == MSG_TYPE_NOP)) {
2579 continue;
2580 }
2581 /* The received message is different from the expected one */
2582 TRACE_MSG("Unexpected control message received (I was expecting a different type of message):\n%s\n", msg);
2583 callDebug("Unexpected control message received (I was expecting a different type of message):\n%s\n\n", msg);
2584 return rejectCall();
2585 } else {
2586 if(extendedTwinSippMode) { // 3pcc extended mode
2587 if(check_peer_src(msg, search_index)) {
2588 found = true;
2589 break;
2590 } else {
2591 WARNING("Unexpected sender for the received peer message \n%s\n", msg);
2592 return rejectCall();
2593 }
2594 } else {
2595 found = true;
2596 break;
2597 }
2598 }
2599 }
2600
2601 if (found) {
2602 call_scenario->messages[search_index]->M_nbCmdRecv ++;
2603 do_bookkeeping(call_scenario->messages[search_index]);
2604
2605 // variable treatment
2606 // Remove \r, \n at the end of a received command
2607 // (necessary for transport, to be removed for usage)
2608 while ( (msg[strlen(msg)-1] == '\n') &&
2609 (msg[strlen(msg)-2] == '\r') ) {
2610 msg[strlen(msg)-2] = 0;
2611 }
2612 actionResult = executeAction(msg, call_scenario->messages[search_index]);
2613
2614 if(actionResult != call::E_AR_NO_ERROR) {
2615 // Store last action result if it is an error
2616 // and go on with the scenario
2617 call::last_action_result = actionResult;
2618 if (actionResult == E_AR_STOP_CALL) {
2619 return rejectCall();
2620 } else if (actionResult == E_AR_CONNECT_FAILED) {
2621 terminate(CStat::E_FAILED_TCP_CONNECT);
2622 return false;
2623 }
2624 }
2625 } else {
2626 TRACE_MSG("Unexpected control message received (no such message found):\n%s\n", msg);
2627 callDebug("Unexpected control message received (no such message found):\n%s\n\n", msg);
2628 return rejectCall();
2629 }
2630 msg_index = search_index; //update the state machine
2631 return(next());
2632 } else {
2633 return (false);
2634 }
2635 }
2636
checkInternalCmd(char * cmd)2637 bool call::checkInternalCmd(char * cmd)
2638 {
2639
2640 char * L_ptr1, * L_ptr2, L_backup;
2641
2642 L_ptr1 = strstr(cmd, "internal-cmd:");
2643 if (!L_ptr1) {
2644 return (false);
2645 }
2646 L_ptr1 += 13 ;
2647 while((*L_ptr1 == ' ') || (*L_ptr1 == '\t')) {
2648 L_ptr1++;
2649 }
2650 if (!(*L_ptr1)) {
2651 return (false);
2652 }
2653 L_ptr2 = L_ptr1;
2654 while((*L_ptr2) &&
2655 (*L_ptr2 != ' ') &&
2656 (*L_ptr2 != '\t') &&
2657 (*L_ptr2 != '\r') &&
2658 (*L_ptr2 != '\n')) {
2659 L_ptr2 ++;
2660 }
2661 if(!*L_ptr2) {
2662 return (false);
2663 }
2664 L_backup = *L_ptr2;
2665 *L_ptr2 = 0;
2666
2667 if (strcmp(L_ptr1, "abort_call") == 0) {
2668 *L_ptr2 = L_backup;
2669 computeStat(CStat::E_CALL_FAILED);
2670 abortCall(true);
2671 return (true);
2672 }
2673
2674 *L_ptr2 = L_backup;
2675 return (false);
2676 }
2677
check_peer_src(char * msg,int search_index)2678 bool call::check_peer_src(char * msg, int search_index)
2679 {
2680 char * L_ptr1, * L_ptr2, L_backup ;
2681
2682 L_ptr1 = strstr(msg, "From:");
2683 if (!L_ptr1) {
2684 return (false);
2685 }
2686 L_ptr1 += 5 ;
2687 while((*L_ptr1 == ' ') || (*L_ptr1 == '\t')) {
2688 L_ptr1++;
2689 }
2690 if (!(*L_ptr1)) {
2691 return (false);
2692 }
2693 L_ptr2 = L_ptr1;
2694 while((*L_ptr2) &&
2695 (*L_ptr2 != ' ') &&
2696 (*L_ptr2 != '\t') &&
2697 (*L_ptr2 != '\r') &&
2698 (*L_ptr2 != '\n')) {
2699 L_ptr2 ++;
2700 }
2701 if(!*L_ptr2) {
2702 return (false);
2703 }
2704 L_backup = *L_ptr2;
2705 *L_ptr2 = 0;
2706 if (strcmp(L_ptr1, call_scenario->messages[search_index] -> peer_src) == 0) {
2707 *L_ptr2 = L_backup;
2708 return(true);
2709 }
2710
2711 *L_ptr2 = L_backup;
2712 return (false);
2713 }
2714
2715
extract_cseq_method(char * method,char * msg)2716 void call::extract_cseq_method (char* method, char* msg)
2717 {
2718 char* cseq ;
2719 if ((cseq = strstr (msg, "CSeq"))) {
2720 char * value ;
2721 if (( value = strchr (cseq, ':'))) {
2722 value++;
2723 while ( isspace(*value)) value++; // ignore any white spaces after the :
2724 while ( !isspace(*value)) value++; // ignore the CSEQ number
2725 while ( isspace(*value)) value++; // ignore spaces after CSEQ number
2726 char *end = value;
2727 int nbytes = 0;
2728 /* A '\r' terminates the line, so we want to catch that too. */
2729 while ((*end != '\r') && (*end != '\n')) {
2730 end++;
2731 nbytes++;
2732 }
2733 if (nbytes > 0) strncpy (method, value, nbytes);
2734 method[nbytes] = '\0';
2735 }
2736 }
2737 }
2738
extract_transaction(char * txn,char * msg)2739 void call::extract_transaction (char* txn, char* msg)
2740 {
2741 char *via = get_header_content(msg, "via:");
2742 if (!via) {
2743 txn[0] = '\0';
2744 return;
2745 }
2746
2747 char *branch = strstr(via, ";branch=");
2748 if (!branch) {
2749 txn[0] = '\0';
2750 return;
2751 }
2752
2753 branch += strlen(";branch=");
2754 while (*branch && *branch != ';' && *branch != ',' && !isspace(*branch)) {
2755 *txn++ = *branch++;
2756 }
2757 *txn = '\0';
2758 }
2759
formatNextReqUrl(char * next_req_url)2760 void call::formatNextReqUrl (char* next_req_url)
2761 {
2762
2763 /* clean up the next_req_url -- Record routes may have extra gunk
2764 that needs to be removed
2765 */
2766 char* actual_req_url = strchr(next_req_url, '<');
2767 if (actual_req_url) {
2768 /* using a temporary buffer */
2769 char tempBuffer[MAX_HEADER_LEN];
2770 strncpy(tempBuffer, actual_req_url + 1, sizeof(tempBuffer) - 1);
2771 actual_req_url = strrchr(tempBuffer, '>');
2772 *actual_req_url = '\0';
2773 strcpy(next_req_url, tempBuffer);
2774 }
2775
2776 }
2777
computeRouteSetAndRemoteTargetUri(char * rr,char * contact,bool bRequestIncoming)2778 void call::computeRouteSetAndRemoteTargetUri (char* rr, char* contact, bool bRequestIncoming)
2779 {
2780 if (0 >=strlen (rr)) {
2781 //
2782 // there are no RR headers. Simply set up the contact as our target uri
2783 //
2784 if (0 < strlen(contact)) {
2785 strcpy (next_req_url, contact);
2786 }
2787
2788 formatNextReqUrl(next_req_url);
2789
2790 return;
2791 }
2792
2793 char actual_rr[MAX_HEADER_LEN];
2794 char targetURI[MAX_HEADER_LEN];
2795 memset(actual_rr, 0, sizeof(actual_rr));
2796
2797 bool isFirst = true;
2798 bool bCopyContactToRR = false;
2799
2800 while (1) {
2801 char* pointer = NULL;
2802 if (bRequestIncoming) {
2803 pointer = strchr (rr, ',');
2804 } else {
2805 pointer = strrchr(rr, ',');
2806 }
2807
2808 if (pointer) {
2809 if (!isFirst) {
2810 if (strlen(actual_rr) ) {
2811 strcat(actual_rr, pointer + 1);
2812 } else {
2813 strcpy(actual_rr, pointer + 1);
2814 }
2815 strcat(actual_rr, ",");
2816 } else {
2817 isFirst = false;
2818 if (NULL == strstr (pointer, ";lr")) {
2819 /* bottom most RR is the next_req_url */
2820 strncpy(targetURI, pointer + 1, sizeof(targetURI) - 1);
2821 bCopyContactToRR = true;
2822 } else {
2823 /* the hop is a loose router. Thus, the target URI should be the
2824 * contact
2825 */
2826 strcpy (targetURI, contact);
2827 strcpy(actual_rr, pointer + 1);
2828 strcat(actual_rr, ",");
2829 }
2830 }
2831 } else {
2832 if (!isFirst) {
2833 strcat(actual_rr, rr);
2834 }
2835 //
2836 // this is the *only* RR header that was found
2837 //
2838 else {
2839 if (NULL == strstr (rr, ";lr")) {
2840 /* bottom most RR is the next_req_url */
2841 strcpy (targetURI, rr);
2842 bCopyContactToRR = true;
2843 } else {
2844 /* the hop is a loose router. Thus, the target URI should be the
2845 * contact
2846 */
2847 strcpy (actual_rr, rr);
2848 strcpy (targetURI, contact);
2849 }
2850 }
2851 break;
2852 }
2853 *pointer = '\0';
2854 }
2855
2856 if (bCopyContactToRR) {
2857 if (0 < strlen (actual_rr)) {
2858 strcat(actual_rr, ",");
2859 strcat(actual_rr, contact);
2860 } else {
2861 strcpy(actual_rr, contact);
2862 }
2863 }
2864
2865 if (strlen(actual_rr)) {
2866 dialog_route_set = (char *)
2867 calloc(1, strlen(actual_rr) + 2);
2868 sprintf(dialog_route_set, "%s", actual_rr);
2869 }
2870
2871 if (strlen (targetURI)) {
2872 strcpy (next_req_url, targetURI);
2873 formatNextReqUrl (next_req_url);
2874 }
2875 }
2876
matches_scenario(unsigned int index,int reply_code,char * request,char * responsecseqmethod,char * txn)2877 bool call::matches_scenario(unsigned int index, int reply_code, char * request, char * responsecseqmethod, char *txn)
2878 {
2879 message *curmsg = call_scenario->messages[index];
2880
2881 if ((curmsg -> recv_request)) {
2882 if (curmsg->regexp_match) {
2883 if (curmsg -> regexp_compile == NULL) {
2884 regex_t *re = new regex_t;
2885 if (regcomp(re, curmsg -> recv_request, REG_EXTENDED|REG_NOSUB)) {
2886 ERROR("Invalid regular expression for index %d: %s", index, curmsg->recv_request);
2887 }
2888 curmsg -> regexp_compile = re;
2889 }
2890 return !regexec(curmsg -> regexp_compile, request, (size_t)0, NULL, 0);
2891 } else {
2892 return !strcmp(curmsg -> recv_request, request);
2893 }
2894 } else if (curmsg->recv_response && (curmsg->recv_response == reply_code)) {
2895 /* This is a potential candidate, we need to match transactions. */
2896 if (curmsg->response_txn) {
2897 if (transactions[curmsg->response_txn - 1].txnID && !strcmp(transactions[curmsg->response_txn - 1].txnID, txn)) {
2898 return true;
2899 } else {
2900 return false;
2901 }
2902 } else if (index == 0) {
2903 /* Always true for the first message. */
2904 return true;
2905 } else if (curmsg->recv_response_for_cseq_method_list &&
2906 strstr(curmsg->recv_response_for_cseq_method_list, responsecseqmethod)) {
2907 /* If we do not have a transaction defined, we just check the CSEQ method. */
2908 return true;
2909 } else {
2910 return false;
2911 }
2912 }
2913
2914 return false;
2915 }
2916
queue_up(char * msg)2917 void call::queue_up(char *msg)
2918 {
2919 free(queued_msg);
2920 queued_msg = strdup(msg);
2921 }
2922
process_incoming(char * msg,struct sockaddr_storage * src)2923 bool call::process_incoming(char * msg, struct sockaddr_storage *src)
2924 {
2925 int reply_code;
2926 static char request[65];
2927 char responsecseqmethod[65];
2928 char txn[MAX_HEADER_LEN];
2929 unsigned long cookie = 0;
2930 char * ptr;
2931 int search_index;
2932 bool found = false;
2933 T_ActionResult actionResult;
2934
2935 getmilliseconds();
2936 callDebug("Processing %zu byte incoming message for call-ID %s (hash %lu):\n%s\n\n",
2937 strlen(msg), id, hash(msg), msg);
2938
2939 setRunning();
2940
2941 /* Ignore the messages received during a pause if -pause_msg_ign is set */
2942 if(call_scenario->messages[msg_index] -> M_type == MSG_TYPE_PAUSE && pause_msg_ign) return(true);
2943
2944 /* Get our destination if we have none. */
2945 if (call_peer.ss_family == AF_UNSPEC && src) {
2946 memcpy(&call_peer, src, SOCK_ADDR_SIZE(src));
2947 }
2948
2949 /* Authorize nop as a first command, even in server mode */
2950 if((msg_index == 0) && (call_scenario->messages[msg_index] -> M_type == MSG_TYPE_NOP)) {
2951 queue_up (msg);
2952 paused_until = 0;
2953 return run();
2954 }
2955 responsecseqmethod[0] = '\0';
2956 txn[0] = '\0';
2957
2958 /* Check that we have a To:-header */
2959 if (!get_header(msg, "To:", false)[0] && !process_unexpected(msg)) {
2960 return false;
2961 }
2962
2963 if ((transport == T_UDP) && (retrans_enabled)) {
2964 /* Detects retransmissions from peer and retransmit the
2965 * message which was sent just after this one was received */
2966 cookie = hash(msg);
2967 if((recv_retrans_recv_index >= 0) && (recv_retrans_hash == cookie)) {
2968
2969 int status;
2970
2971 if(lost(recv_retrans_recv_index)) {
2972 TRACE_MSG("%s message (retrans) lost (recv).",
2973 TRANSPORT_TO_STRING(transport));
2974 callDebug("%s message (retrans) lost (recv) (hash %lu)\n", TRANSPORT_TO_STRING(transport), hash(msg));
2975
2976 if(comp_state) {
2977 comp_free(&comp_state);
2978 }
2979 call_scenario->messages[recv_retrans_recv_index] -> nb_lost++;
2980 return true;
2981 }
2982
2983 call_scenario->messages[recv_retrans_recv_index] -> nb_recv_retrans++;
2984
2985 send_scene(recv_retrans_send_index, &status, NULL);
2986
2987 if(status >= 0) {
2988 call_scenario->messages[recv_retrans_send_index] -> nb_sent_retrans++;
2989 computeStat(CStat::E_RETRANSMISSION);
2990 } else if(status < 0) {
2991 return false;
2992 }
2993
2994 return true;
2995 }
2996
2997 if((last_recv_index >= 0) && (last_recv_hash == cookie)) {
2998 /* This one has already been received, but not processed
2999 * yet => (has not triggered something yet) so we can discard.
3000 *
3001 * This case appears when the UAS has send a 200 but not received
3002 * a ACK yet. Thus, the UAS retransmit the 200 (invite transaction)
3003 * until it receives a ACK. In this case, it nevers sends the 200
3004 * from the BYE, until it has reveiced the previous 200. Thus,
3005 * the UAC retransmit the BYE, and this BYE is considered as an
3006 * unexpected.
3007 *
3008 * This case can also appear in case of message duplication by
3009 * the network. This should not be considered as an unexpected.
3010 */
3011 call_scenario->messages[last_recv_index]->nb_recv_retrans++;
3012 return true;
3013 }
3014 }
3015
3016 #ifdef RTP_STREAM
3017 /* Check if message has a SDP in it; and extract media information. */
3018 if (!strcmp(get_header_content(msg, (char*)"Content-Type:"),"application/sdp") &&
3019 (hasMedia == 1)) {
3020 extract_rtp_remote_addr(msg);
3021 }
3022 #endif
3023
3024 /* Is it a response ? */
3025 if((msg[0] == 'S') &&
3026 (msg[1] == 'I') &&
3027 (msg[2] == 'P') &&
3028 (msg[3] == '/') &&
3029 (msg[4] == '2') &&
3030 (msg[5] == '.') &&
3031 (msg[6] == '0') ) {
3032
3033 reply_code = get_reply_code(msg);
3034 if(!reply_code) {
3035 if (!process_unexpected(msg)) {
3036 return false; // Call aborted by unexpected message handling
3037 }
3038 #ifdef PCAPPLAY
3039 } else if ((hasMedia == 1) && *(strstr(msg, "\r\n\r\n")+4) != '\0') {
3040 /* Get media info if we find something like an SDP */
3041 get_remote_media_addr(msg);
3042 #endif
3043 }
3044 /* It is a response: update peer_tag */
3045 ptr = get_peer_tag(msg);
3046 if (ptr) {
3047 if(strlen(ptr) > (MAX_HEADER_LEN - 1)) {
3048 ERROR("Peer tag too long. Change MAX_HEADER_LEN and recompile sipp");
3049 }
3050 if(peer_tag) {
3051 free(peer_tag);
3052 }
3053 peer_tag = strdup(ptr);
3054 if (!peer_tag) {
3055 ERROR("Out of memory allocating peer tag.");
3056 }
3057 }
3058 request[0]=0;
3059 // extract the cseq method from the response
3060 extract_cseq_method (responsecseqmethod, msg);
3061 extract_transaction (txn, msg);
3062 } else if((ptr = strchr(msg, ' '))) {
3063 if((ptr - msg) < 64) {
3064 memcpy(request, msg, ptr - msg);
3065 request[ptr - msg] = 0;
3066 // Check if we received an ACK => call established
3067 if (strcmp(request,"ACK")==0) {
3068 call_established=true;
3069 }
3070 #ifdef PCAPPLAY
3071 /* In case of INVITE or re-INVITE, ACK or PRACK
3072 get the media info if needed (= we got a pcap
3073 play action) */
3074 if (((strncmp(request, "INVITE", 6) == 0)
3075 || (strncmp(request, "ACK", 3) == 0)
3076 || (strncmp(request, "PRACK", 5) == 0))
3077 && (hasMedia == 1))
3078 get_remote_media_addr(msg);
3079 #endif
3080
3081 reply_code = 0;
3082 } else {
3083 ERROR("SIP method too long in received message '%s'",
3084 msg);
3085 }
3086 } else {
3087 ERROR("Invalid sip message received '%s'",
3088 msg);
3089 }
3090
3091 /* Try to find it in the expected non mandatory responses
3092 * until the first mandatory response in the scenario */
3093 for(search_index = msg_index;
3094 search_index < (int)call_scenario->messages.size();
3095 search_index++) {
3096 if(!matches_scenario(search_index, reply_code, request, responsecseqmethod, txn)) {
3097 if(call_scenario->messages[search_index] -> optional) {
3098 continue;
3099 }
3100 /* The received message is different for the expected one */
3101 break;
3102 }
3103
3104 found = true;
3105 /* TODO : this is a little buggy: If a 100 trying from an INVITE
3106 * is delayed by the network until the BYE is sent, it may
3107 * stop BYE transmission erroneously, if the BYE also expects
3108 * a 100 trying. */
3109 break;
3110 }
3111
3112 /* Try to find it in the old non-mandatory receptions */
3113 if(!found) {
3114 bool contig = true;
3115 for(search_index = msg_index - 1;
3116 search_index >= 0;
3117 search_index--) {
3118 if (call_scenario->messages[search_index]->optional == OPTIONAL_FALSE) contig = false;
3119 if(matches_scenario(search_index, reply_code, request, responsecseqmethod, txn)) {
3120 if (contig || call_scenario->messages[search_index]->optional == OPTIONAL_GLOBAL) {
3121 found = true;
3122 break;
3123 } else {
3124 if (int checkTxn = call_scenario->messages[search_index]->response_txn) {
3125 /* This is a reply to an old transaction. */
3126 if (!strcmp(transactions[checkTxn - 1].txnID, txn)) {
3127 /* This reply is provisional, so it should have no effect if we recieve it out-of-order. */
3128 if (reply_code >= 100 && reply_code <= 199) {
3129 TRACE_MSG("-----------------------------------------------\n"
3130 "Ignoring provisional %s message for transaction %s:\n\n%s\n",
3131 TRANSPORT_TO_STRING(transport), call_scenario->transactions[checkTxn - 1].name, msg);
3132 callDebug("Ignoring provisional %s message for transaction %s (hash %lu):\n\n%s\n",
3133 TRANSPORT_TO_STRING(transport), call_scenario->transactions[checkTxn - 1].name, hash(msg), msg);
3134 return true;
3135 } else if (int ackIndex = transactions[checkTxn - 1].ackIndex) {
3136 /* This is the message before an ACK, so verify that this is an invite transaction. */
3137 assert (call_scenario->transactions[checkTxn - 1].isInvite);
3138 sendBuffer(createSendingMessage(call_scenario->messages[ackIndex] -> send_scheme, ackIndex));
3139 return true;
3140 } else {
3141 assert (!call_scenario->transactions[checkTxn - 1].isInvite);
3142 /* This is a non-provisional message for the transaction, and
3143 * we have already gotten our allowable response. Just make sure
3144 * that it is not a retransmission of the final response. */
3145 if (transactions[checkTxn - 1].txnResp == hash(msg)) {
3146 /* We have gotten this retransmission out-of-order, let's just ignore it. */
3147 TRACE_MSG("-----------------------------------------------\n"
3148 "Ignoring final %s message for transaction %s:\n\n%s\n",
3149 TRANSPORT_TO_STRING(transport), call_scenario->transactions[checkTxn - 1].name, msg);
3150 callDebug("Ignoring final %s message for transaction %s (hash %lu):\n\n%s\n",
3151 TRANSPORT_TO_STRING(transport), call_scenario->transactions[checkTxn - 1].name, hash(msg), msg);
3152 WARNING("Ignoring final %s message for transaction %s (hash %lu):\n\n%s\n",
3153 TRANSPORT_TO_STRING(transport), call_scenario->transactions[checkTxn - 1].name, hash(msg), msg);
3154 return true;
3155 }
3156 }
3157 }
3158 } else {
3159 /*
3160 * we received a non mandatory msg for an old transaction (this could be due to a retransmit.
3161 * If this response is for an INVITE transaction, retransmit the ACK to quench retransmits.
3162 */
3163 if ( (reply_code) &&
3164 (0 == strncmp (responsecseqmethod, "INVITE", strlen(responsecseqmethod)) ) &&
3165 (call_scenario->messages[search_index+1]->M_type == MSG_TYPE_SEND) &&
3166 (call_scenario->messages[search_index+1]->send_scheme->isAck()) ) {
3167 sendBuffer(createSendingMessage(call_scenario->messages[search_index+1] -> send_scheme, (search_index+1)));
3168 return true;
3169 }
3170 }
3171 }
3172 }
3173 }
3174 }
3175
3176 /* If it is still not found, process an unexpected message */
3177 if(!found) {
3178 if (call_scenario->unexpected_jump >= 0) {
3179 bool recursive = false;
3180 if (call_scenario->retaddr >= 0) {
3181 if (M_callVariableTable->getVar(call_scenario->retaddr)->getDouble() != 0) {
3182 /* We are already in a jump! */
3183 recursive = true;
3184 } else {
3185 M_callVariableTable->getVar(call_scenario->retaddr)->setDouble(msg_index);
3186 }
3187 }
3188 if (!recursive) {
3189 if (call_scenario->pausedaddr >= 0) {
3190 M_callVariableTable->getVar(call_scenario->pausedaddr)->setDouble(paused_until);
3191 }
3192 msg_index = call_scenario->unexpected_jump;
3193 queue_up(msg);
3194 paused_until = 0;
3195 return run();
3196 } else {
3197 if (!process_unexpected(msg)) {
3198 return false; // Call aborted by unexpected message handling
3199 }
3200 }
3201 } else {
3202 T_AutoMode L_case;
3203 if ((L_case = checkAutomaticResponseMode(request)) == 0) {
3204 if (!process_unexpected(msg)) {
3205 return false; // Call aborted by unexpected message handling
3206 }
3207 } else {
3208 // call aborted by automatic response mode if needed
3209 return automaticResponseMode(L_case, msg);
3210 }
3211 }
3212 }
3213
3214 int test = (!found) ? -1 : call_scenario->messages[search_index]->test;
3215 /* test==0: No branching"
3216 * test==-1 branching without testing"
3217 * test>0 branching with testing
3218 */
3219
3220 /* Simulate loss of messages */
3221 if(lost(search_index)) {
3222 TRACE_MSG("%s message lost (recv).",
3223 TRANSPORT_TO_STRING(transport));
3224 callDebug("%s message lost (recv) (hash %lu).\n",
3225 TRANSPORT_TO_STRING(transport), hash(msg));
3226 if(comp_state) {
3227 comp_free(&comp_state);
3228 }
3229 call_scenario->messages[search_index] -> nb_lost++;
3230 return true;
3231 }
3232
3233 /* If we are part of a transaction, mark this as the final response. */
3234 if (int checkTxn = call_scenario->messages[search_index]->response_txn) {
3235 transactions[checkTxn - 1].txnResp = hash(msg);
3236 }
3237
3238
3239 /* Handle counters and RTDs for this message. */
3240 do_bookkeeping(call_scenario->messages[search_index]);
3241
3242 /* Increment the recv counter */
3243 call_scenario->messages[search_index] -> nb_recv++;
3244
3245 // Action treatment
3246 if (found) {
3247 //WARNING("---EXECUTE_ACTION_ON_MSG---%s---", msg);
3248
3249 actionResult = executeAction(msg, call_scenario->messages[search_index]);
3250
3251 if(actionResult != call::E_AR_NO_ERROR) {
3252 // Store last action result if it is an error
3253 // and go on with the scenario
3254 call::last_action_result = actionResult;
3255 if (actionResult == E_AR_STOP_CALL) {
3256 return rejectCall();
3257 } else if (actionResult == E_AR_CONNECT_FAILED) {
3258 terminate(CStat::E_FAILED_TCP_CONNECT);
3259 return false;
3260 }
3261 }
3262 }
3263
3264 if (*request) { // update [cseq] with received CSeq
3265 unsigned long int rcseq = get_cseq_value(msg);
3266 if (rcseq > cseq) cseq = rcseq;
3267 }
3268
3269 /* This is an ACK/PRACK or a response, and its index is greater than the
3270 * current active retransmission message, so we stop the retrans timer.
3271 * True also for CANCEL and BYE that we also want to answer to */
3272 if(((reply_code) ||
3273 ((!strcmp(request, "ACK")) ||
3274 (!strcmp(request, "CANCEL")) || (!strcmp(request, "BYE")) ||
3275 (!strcmp(request, "PRACK")))) &&
3276 (search_index > last_send_index)) {
3277 /*
3278 * We should stop any retransmission timers on receipt of a provisional response only for INVITE
3279 * transactions. Non INVITE transactions continue to retransmit at T2 until a final response is
3280 * received
3281 */
3282 if ( (0 == reply_code) || // means this is a request.
3283 (200 <= reply_code) || // final response
3284 ((0 != reply_code) && (0 == strncmp (responsecseqmethod, "INVITE", strlen(responsecseqmethod)))) ) { // prov for INVITE
3285 next_retrans = 0;
3286 } else {
3287 /*
3288 * We are here due to a provisional response for non INVITE. Update our next retransmit.
3289 */
3290 next_retrans = clock_tick + global_t2;
3291 nb_last_delay = global_t2;
3292
3293 }
3294 }
3295
3296 /* This is a response with 200 so set the flag indicating that an
3297 * ACK is pending (used to prevent from release a call with CANCEL
3298 * when an ACK+BYE should be sent instead) */
3299 if (reply_code == 200) {
3300 ack_is_pending = true;
3301 }
3302
3303 /* store the route set only once. TODO: does not support target refreshes!! */
3304 if (call_scenario->messages[search_index] -> bShouldRecordRoutes &&
3305 NULL == dialog_route_set ) {
3306
3307 realloc_ptr = (char*) realloc(next_req_url, MAX_HEADER_LEN);
3308 if (realloc_ptr) {
3309 next_req_url = realloc_ptr;
3310 } else {
3311 free(next_req_url);
3312 ERROR("Out of memory!");
3313 return false;
3314 }
3315
3316
3317 char rr[MAX_HEADER_LEN];
3318 memset(rr, 0, sizeof(rr));
3319 strncpy(rr, get_header_content(msg, (char*)"Record-Route:"), sizeof(rr) - 1);
3320
3321 // WARNING("rr [%s]", rr);
3322 char ch[MAX_HEADER_LEN];
3323 strncpy(ch, get_header_content(msg, (char*)"Contact:"), sizeof(rr) - 1);
3324
3325 /* decorate the contact with '<' and '>' if it does not have it */
3326 char* contDecorator = strchr(ch, '<');
3327 if (NULL == contDecorator) {
3328 char tempBuffer[MAX_HEADER_LEN];
3329 sprintf(tempBuffer, "<%s>", ch);
3330 strcpy(ch, tempBuffer);
3331 }
3332
3333 /* should cache the route set */
3334 if (reply_code) {
3335 computeRouteSetAndRemoteTargetUri (rr, ch, false);
3336 } else {
3337 computeRouteSetAndRemoteTargetUri (rr, ch, true);
3338 }
3339 // WARNING("next_req_url is [%s]", next_req_url);
3340 }
3341
3342 /* store the authentication info */
3343 if ((call_scenario->messages[search_index] -> bShouldAuthenticate) &&
3344 (reply_code == 401 || reply_code == 407)) {
3345
3346 /* is a challenge */
3347 char auth[MAX_HEADER_LEN];
3348 memset(auth, 0, sizeof(auth));
3349 strncpy(auth, get_header_content(msg, (char*)"Proxy-Authenticate:"), sizeof(auth) - 1);
3350 if (auth[0] == 0) {
3351 strncpy(auth, get_header_content(msg, (char*)"WWW-Authenticate:"), sizeof(auth) - 1);
3352 }
3353 if (auth[0] == 0) {
3354 ERROR("Couldn't find 'Proxy-Authenticate' or 'WWW-Authenticate' in 401 or 407!");
3355 }
3356
3357 realloc_ptr = (char *) realloc(dialog_authentication, strlen(auth) + 2);
3358 if (realloc_ptr) {
3359 dialog_authentication = realloc_ptr;
3360 } else {
3361 free(dialog_authentication);
3362 ERROR("Out of memory!");
3363 return false;
3364 }
3365
3366
3367 sprintf(dialog_authentication, "%s", auth);
3368
3369 /* Store the code of the challenge for building the proper header */
3370 dialog_challenge_type = reply_code;
3371 }
3372
3373 /* If we are not advancing state, we should quite before we change this stuff. */
3374 if (!call_scenario->messages[search_index]->advance_state) {
3375 return true;
3376 }
3377
3378 /* Store last received message information for all messages so that we can
3379 * correctly identify retransmissions, and use its body for inclusion
3380 * in our messages. */
3381 last_recv_index = search_index;
3382 last_recv_hash = cookie;
3383 callDebug("Set Last Recv Hash: %lu (recv index %d)\n", last_recv_hash, last_recv_index);
3384 realloc_ptr = (char *) realloc(last_recv_msg, strlen(msg) + 1);
3385 if (realloc_ptr) {
3386 last_recv_msg = realloc_ptr;
3387 } else {
3388 free(last_recv_msg);
3389 ERROR("Out of memory!");
3390 return false;
3391 }
3392
3393
3394 strcpy(last_recv_msg, msg);
3395
3396 /* If this was a mandatory message, or if there is an explicit next label set
3397 * we must update our state machine. */
3398 if (!call_scenario->messages[search_index]->optional ||
3399 (call_scenario->messages[search_index]->next &&
3400 (test == -1 || M_callVariableTable->getVar(test)->isSet()))) {
3401 /* If we are paused, then we need to wake up so that we properly go through the state machine. */
3402 paused_until = 0;
3403 msg_index = search_index;
3404 return next();
3405 } else {
3406 unsigned int timeout = wake();
3407 unsigned int candidate;
3408
3409 if (call_scenario->messages[search_index]->next && M_callVariableTable->getVar(test)->isSet()) {
3410 WARNING("Last message generates an error and will not be used for next sends (for last_ variables):\r\n%s",msg);
3411 }
3412
3413 /* We are just waiting for a message to be received, if any of the
3414 * potential messages have a timeout we set it as our timeout. We
3415 * start from the next message and go until any non-receives. */
3416 for(search_index++; search_index < (int)call_scenario->messages.size(); search_index++) {
3417 if(call_scenario->messages[search_index] -> M_type != MSG_TYPE_RECV) {
3418 break;
3419 }
3420 candidate = call_scenario->messages[search_index] -> timeout;
3421 if (candidate == 0) {
3422 if (defl_recv_timeout == 0) {
3423 continue;
3424 }
3425 candidate = defl_recv_timeout;
3426 }
3427 if (!timeout || (clock_tick + candidate < timeout)) {
3428 timeout = clock_tick + candidate;
3429 }
3430 }
3431
3432 setPaused();
3433 }
3434 return true;
3435 }
3436
get_rhs(CAction * currentAction)3437 double call::get_rhs(CAction *currentAction)
3438 {
3439 if (currentAction->getVarInId()) {
3440 return M_callVariableTable->getVar(currentAction->getVarInId())->getDouble();
3441 } else {
3442 return currentAction->getDoubleValue();
3443 }
3444 }
3445
executeAction(char * msg,message * curmsg)3446 call::T_ActionResult call::executeAction(char * msg, message *curmsg)
3447 {
3448 CActions* actions;
3449 CAction* currentAction;
3450
3451 actions = curmsg->M_actions;
3452 // looking for action to do on this message
3453 if(actions == NULL) {
3454 return(call::E_AR_NO_ERROR);
3455 }
3456
3457 for(int i=0; i<actions->getActionSize(); i++) {
3458 currentAction = actions->getAction(i);
3459 if(currentAction == NULL) {
3460 continue;
3461 }
3462
3463 if(currentAction->getActionType() == CAction::E_AT_ASSIGN_FROM_REGEXP) {
3464 char msgPart[MAX_SUB_MESSAGE_LENGTH];
3465
3466 /* Where to look. */
3467 char *haystack;
3468
3469 if(currentAction->getLookingPlace() == CAction::E_LP_HDR) {
3470 extractSubMessage (msg,
3471 currentAction->getLookingChar(),
3472 msgPart,
3473 currentAction->getCaseIndep(),
3474 currentAction->getOccurrence(),
3475 currentAction->getHeadersOnly());
3476 if(currentAction->getCheckIt() == true && (strlen(msgPart) == 0)) {
3477 // the sub message is not found and the checking action say it
3478 // MUST match --> Call will be marked as failed but will go on
3479 WARNING("Failed regexp match: header %s not found in message %s\n", currentAction->getLookingChar(), msg);
3480 return(call::E_AR_HDR_NOT_FOUND);
3481 }
3482 haystack = msgPart;
3483 } else if(currentAction->getLookingPlace() == CAction::E_LP_BODY) {
3484 haystack = strstr(msg, "\r\n\r\n");
3485 if (!haystack) {
3486 if (currentAction->getCheckIt() == true) {
3487 WARNING("Failed regexp match: body not found in message %s\n", msg);
3488 return(call::E_AR_HDR_NOT_FOUND);
3489 }
3490 msgPart[0] = '\0';
3491 haystack = msgPart;
3492 }
3493 haystack += strlen("\r\n\r\n");
3494 } else if(currentAction->getLookingPlace() == CAction::E_LP_MSG) {
3495 haystack = msg;
3496 } else if(currentAction->getLookingPlace() == CAction::E_LP_VAR) {
3497 /* Get the input variable. */
3498 haystack = M_callVariableTable->getVar(currentAction->getVarInId())->getString();
3499 if (!haystack) {
3500 if (currentAction->getCheckIt() == true) {
3501 WARNING("Failed regexp match: variable $%d not set\n", currentAction->getVarInId());
3502 return(call::E_AR_HDR_NOT_FOUND);
3503 }
3504 }
3505 } else {
3506 ERROR("Invalid looking place: %d\n", currentAction->getLookingPlace());
3507 }
3508 bool did_match = (currentAction->executeRegExp(haystack, M_callVariableTable) > 0);
3509
3510 if (!did_match && currentAction->getCheckIt()) {
3511 // the message doesn't match and the checkit action say it MUST match
3512 // Allow easier regexp debugging
3513 WARNING("Failed regexp match: looking in '%s', with regexp '%s'",
3514 haystack, currentAction->getRegularExpression());
3515 return(call::E_AR_REGEXP_DOESNT_MATCH);
3516 } else if (did_match && currentAction->getCheckItInverse()) {
3517 // The inverse of the above
3518 WARNING("Regexp matched but should not: looking in '%s', with regexp '%s'",
3519 haystack, currentAction->getRegularExpression());
3520 return(call::E_AR_REGEXP_SHOULDNT_MATCH);
3521 }
3522 } else if (currentAction->getActionType() == CAction::E_AT_ASSIGN_FROM_VALUE) {
3523 double operand = get_rhs(currentAction);
3524 M_callVariableTable->getVar(currentAction->getVarId())->setDouble(operand);
3525 } else if (currentAction->getActionType() == CAction::E_AT_ASSIGN_FROM_INDEX) {
3526 M_callVariableTable->getVar(currentAction->getVarId())->setDouble(msg_index);
3527 } else if (currentAction->getActionType() == CAction::E_AT_ASSIGN_FROM_GETTIMEOFDAY) {
3528 struct timeval tv;
3529 gettimeofday(&tv, NULL);
3530 M_callVariableTable->getVar(currentAction->getVarId())->setDouble((double)tv.tv_sec);
3531 M_callVariableTable->getVar(currentAction->getSubVarId(0))->setDouble((double)tv.tv_usec);
3532 } else if (currentAction->getActionType() == CAction::E_AT_LOOKUP) {
3533 /* Create strings from the sending messages. */
3534 char *file = strdup(createSendingMessage(currentAction->getMessage(0), -2));
3535 char *key = strdup(createSendingMessage(currentAction->getMessage(1), -2));
3536
3537 if (inFiles.find(file) == inFiles.end()) {
3538 ERROR("Invalid injection file for insert: %s", file);
3539 }
3540
3541 double value = inFiles[file]->lookup(key);
3542
3543 M_callVariableTable->getVar(currentAction->getVarId())->setDouble(value);
3544 free(file);
3545 free(key);
3546 } else if (currentAction->getActionType() == CAction::E_AT_INSERT) {
3547 /* Create strings from the sending messages. */
3548 char *file = strdup(createSendingMessage(currentAction->getMessage(0), -2));
3549 char *value = strdup(createSendingMessage(currentAction->getMessage(1), -2));
3550
3551 if (inFiles.find(file) == inFiles.end()) {
3552 ERROR("Invalid injection file for insert: %s", file);
3553 }
3554
3555 inFiles[file]->insert(value);
3556
3557 free(file);
3558 free(value);
3559 } else if (currentAction->getActionType() == CAction::E_AT_REPLACE) {
3560 /* Create strings from the sending messages. */
3561 char *file = strdup(createSendingMessage(currentAction->getMessage(0), -2));
3562 char *line = strdup(createSendingMessage(currentAction->getMessage(1), -2));
3563 char *value = strdup(createSendingMessage(currentAction->getMessage(2), -2));
3564
3565 if (inFiles.find(file) == inFiles.end()) {
3566 ERROR("Invalid injection file for replace: %s", file);
3567 }
3568
3569 char *endptr;
3570 int lineNum = (int)strtod(line, &endptr);
3571 if (*endptr) {
3572 ERROR("Invalid line number for replace: %s", line);
3573 }
3574
3575 inFiles[file]->replace(lineNum, value);
3576
3577 free(file);
3578 free(line);
3579 free(value);
3580 } else if (currentAction->getActionType() == CAction::E_AT_CLOSE_CON) {
3581 if (call_socket) {
3582 sipp_socket_invalidate(call_socket);
3583 sipp_close_socket(call_socket);
3584 call_socket = NULL;
3585 }
3586 } else if (currentAction->getActionType() == CAction::E_AT_SET_DEST) {
3587 /* Change the destination for this call. */
3588 char *str_host = strdup(createSendingMessage(currentAction->getMessage(0), -2));
3589 char *str_port = strdup(createSendingMessage(currentAction->getMessage(1), -2));
3590 char *str_protocol = strdup(createSendingMessage(currentAction->getMessage(2), -2));
3591
3592 char *endptr;
3593 int port = (int)strtod(str_port, &endptr);
3594 if (*endptr) {
3595 ERROR("Invalid port for setdest: %s", str_port);
3596 }
3597
3598 int protocol;
3599 if (!strcmp(str_protocol, "udp") || !strcmp(str_protocol, "UDP")) {
3600 protocol = T_UDP;
3601 } else if (!strcmp(str_protocol, "tcp") || !strcmp(str_protocol, "TCP")) {
3602 protocol = T_TCP;
3603 } else if (!strcmp(str_protocol, "tls") || !strcmp(str_protocol, "TLS")) {
3604 protocol = T_TLS;
3605 } else if (!strcmp(str_protocol, "sctp") || !strcmp(str_protocol, "SCTP")) {
3606 protocol = T_SCTP;
3607 } else {
3608 ERROR("Unknown transport for setdest: '%s'", str_protocol);
3609 }
3610
3611 if (!call_socket && ((protocol == T_TCP && transport == T_TCP) ||
3612 (protocol == T_SCTP && transport == T_SCTP))) {
3613 bool existing;
3614 if ((associate_socket(new_sipp_call_socket(use_ipv6, transport, &existing))) == NULL) {
3615 switch (protocol) {
3616 case T_SCTP:
3617 ERROR_NO("Unable to get a SCTP socket");
3618 break;
3619 default:
3620 ERROR_NO("Unable to get a TCP socket");
3621 }
3622 }
3623
3624 if (!existing) {
3625 sipp_customize_socket(call_socket);
3626 }
3627 }
3628
3629 if (!call_socket) {
3630 ERROR("Unable to get a socket");
3631 }
3632
3633 if (protocol != call_socket->ss_transport) {
3634 ERROR("Can not switch protocols during setdest.");
3635 }
3636
3637 if (protocol == T_UDP) {
3638 /* Nothing to do. */
3639 } else if (protocol == T_TLS) {
3640 ERROR("Changing destinations is not supported for TLS.");
3641 } else if (protocol == T_TCP || protocol == T_SCTP) {
3642 if (!multisocket) {
3643 ERROR("Changing destinations for TCP or SCTP requires multisocket mode.");
3644 }
3645 if (call_socket->ss_count > 1) {
3646 ERROR("Can not change destinations for a TCP/SCTP socket that has more than one user.");
3647 }
3648 }
3649
3650 struct addrinfo hints;
3651 struct addrinfo * local_addr;
3652 memset((char*)&hints, 0, sizeof(hints));
3653 hints.ai_flags = AI_PASSIVE;
3654 hints.ai_family = PF_UNSPEC;
3655 is_ipv6 = false;
3656
3657 if (getaddrinfo(str_host, NULL, &hints, &local_addr) != 0) {
3658 ERROR("Unknown host '%s' for setdest", str_host);
3659 }
3660 if (_RCAST(struct sockaddr_storage *, local_addr->ai_addr)->ss_family != call_peer.ss_family) {
3661 ERROR("Can not switch between IPv4 and IPV6 using setdest!");
3662 }
3663 memcpy(&call_peer, local_addr->ai_addr,
3664 SOCK_ADDR_SIZE(_RCAST(struct sockaddr_storage*, local_addr->ai_addr)));
3665 freeaddrinfo(local_addr);
3666
3667 if (call_peer.ss_family == AF_INET) {
3668 (_RCAST(struct sockaddr_in*, &call_peer))->sin_port = htons(port);
3669 } else {
3670 (_RCAST(struct sockaddr_in6*, &call_peer))->sin6_port = htons(port);
3671 }
3672 memcpy(&call_socket->ss_dest, &call_peer,
3673 SOCK_ADDR_SIZE(_RCAST(struct sockaddr_storage*, &call_peer)));
3674
3675 free(str_host);
3676 free(str_port);
3677 free(str_protocol);
3678
3679 if (protocol == T_TCP || protocol == T_SCTP) {
3680 close(call_socket->ss_fd);
3681 call_socket->ss_fd = -1;
3682 call_socket->ss_changed_dest = true;
3683 if (sipp_reconnect_socket(call_socket)) {
3684 if (reconnect_allowed()) {
3685 if(errno == EINVAL) {
3686 /* This occurs sometime on HPUX but is not a true INVAL */
3687 WARNING("Unable to connect a TCP/SCTP/TLS socket, remote peer error");
3688 } else {
3689 WARNING("Unable to connect a TCP/SCTP/TLS socket");
3690 }
3691 /* This connection failed. We must be in multisocket mode, because
3692 * otherwise we would already have a call_socket. This call can not
3693 * succeed, but does not affect any of our other calls. We do decrement
3694 * the reconnection counter however. */
3695 if (reset_number != -1) {
3696 reset_number--;
3697 }
3698
3699 return E_AR_CONNECT_FAILED;
3700 } else {
3701 if(errno == EINVAL) {
3702 /* This occurs sometime on HPUX but is not a true INVAL */
3703 ERROR("Unable to connect a TCP/SCTP/TLS socket, remote peer error");
3704 } else {
3705 ERROR_NO("Unable to connect a TCP/SCTP/TLS socket");
3706 }
3707 }
3708 }
3709 }
3710 } else if (currentAction->getActionType() == CAction::E_AT_VERIFY_AUTH) {
3711 bool result;
3712 char *lf;
3713 char *end;
3714
3715 lf = strchr(msg, '\n');
3716 end = strchr(msg, ' ');
3717
3718 if (!lf || !end) {
3719 result = false;
3720 } else if (lf < end) {
3721 result = false;
3722 } else {
3723 char *auth = get_header(msg, "Authorization:", true);
3724 char *method = (char *)malloc(end - msg + 1);
3725 strncpy(method, msg, end - msg);
3726 method[end - msg] = '\0';
3727
3728 /* Generate the username to verify it against. */
3729 char *tmp = createSendingMessage(currentAction->getMessage(0), -2 /* do not add crlf*/);
3730 char *username = strdup(tmp);
3731 /* Generate the password to verify it against. */
3732 tmp= createSendingMessage(currentAction->getMessage(1), -2 /* do not add crlf*/);
3733 char *password = strdup(tmp);
3734 /* Need the body for length and auth-int calculation */
3735 char *body;
3736 const char *auth_body = NULL;
3737 body = strstr(msg, "\r\n\r\n");
3738 if (body) {
3739 auth_body = body;
3740 auth_body += strlen("\r\n\r\n");
3741 } else {
3742 auth_body = "";
3743 }
3744
3745 result = verifyAuthHeader(username, password, method, auth, auth_body);
3746
3747 free(username);
3748 free(password);
3749 free(method);
3750 }
3751
3752 M_callVariableTable->getVar(currentAction->getVarId())->setBool(result);
3753 } else if (currentAction->getActionType() == CAction::E_AT_JUMP) {
3754 double operand = get_rhs(currentAction);
3755 if (msg_index == ((int)operand)) {
3756 ERROR("Jump statement at index %d jumps to itself and causes an infinite loop", msg_index);
3757 }
3758 msg_index = (int)operand - 1;
3759 /* -1 is allowed to go to the first label, but watch out
3760 * when using msg_index. */
3761 if (msg_index < -1 || msg_index >= (int)call_scenario->messages.size()) {
3762 ERROR("Jump statement out of range (not 0 <= %d <= %zu)",
3763 msg_index + 1, call_scenario->messages.size());
3764 }
3765 } else if (currentAction->getActionType() == CAction::E_AT_PAUSE_RESTORE) {
3766 double operand = get_rhs(currentAction);
3767 paused_until = (int)operand;
3768 } else if (currentAction->getActionType() == CAction::E_AT_VAR_ADD) {
3769 double value = M_callVariableTable->getVar(currentAction->getVarId())->getDouble();
3770 double operand = get_rhs(currentAction);
3771 M_callVariableTable->getVar(currentAction->getVarId())->setDouble(value + operand);
3772 } else if (currentAction->getActionType() == CAction::E_AT_VAR_SUBTRACT) {
3773 double value = M_callVariableTable->getVar(currentAction->getVarId())->getDouble();
3774 double operand = get_rhs(currentAction);
3775 M_callVariableTable->getVar(currentAction->getVarId())->setDouble(value - operand);
3776 } else if (currentAction->getActionType() == CAction::E_AT_VAR_MULTIPLY) {
3777 double value = M_callVariableTable->getVar(currentAction->getVarId())->getDouble();
3778 double operand = get_rhs(currentAction);
3779 M_callVariableTable->getVar(currentAction->getVarId())->setDouble(value * operand);
3780 } else if (currentAction->getActionType() == CAction::E_AT_VAR_DIVIDE) {
3781 double value = M_callVariableTable->getVar(currentAction->getVarId())->getDouble();
3782 double operand = get_rhs(currentAction);
3783 if (operand == 0) {
3784 WARNING("Action failure: Can not divide by zero ($%d/$%d)!\n", currentAction->getVarId(), currentAction->getVarInId());
3785 } else {
3786 M_callVariableTable->getVar(currentAction->getVarId())->setDouble(value / operand);
3787 }
3788 } else if (currentAction->getActionType() == CAction::E_AT_VAR_TEST) {
3789 double value = currentAction->compare(M_callVariableTable);
3790 M_callVariableTable->getVar(currentAction->getVarId())->setBool(value);
3791 } else if (currentAction->getActionType() == CAction::E_AT_VAR_STRCMP) {
3792 char *rhs = M_callVariableTable->getVar(currentAction->getVarInId())->getString();
3793 char *lhs;
3794 if (currentAction->getVarIn2Id()) {
3795 lhs = M_callVariableTable->getVar(currentAction->getVarIn2Id())->getString();
3796 } else {
3797 lhs = currentAction->getStringValue();
3798 }
3799 int value = strcmp(rhs, lhs);
3800 M_callVariableTable->getVar(currentAction->getVarId())->setDouble((double)value);
3801 } else if (currentAction->getActionType() == CAction::E_AT_VAR_TRIM) {
3802 CCallVariable *var = M_callVariableTable->getVar(currentAction->getVarId());
3803 char *in = var->getString();
3804 char *p = in;
3805 while (isspace(*p)) {
3806 p++;
3807 }
3808 char *q = strdup(p);
3809 var->setString(q);
3810 int l = strlen(q);
3811 for (int i = l - 1; (i >= 0) && isspace(q[i]); i--) {
3812 q[i] = '\0';
3813 }
3814 } else if (currentAction->getActionType() == CAction::E_AT_VAR_TO_DOUBLE) {
3815 double value;
3816
3817 if (M_callVariableTable->getVar(currentAction->getVarInId())->toDouble(&value)) {
3818 M_callVariableTable->getVar(currentAction->getVarId())->setDouble(value);
3819 } else {
3820 WARNING("Invalid double conversion from $%d to $%d", currentAction->getVarInId(), currentAction->getVarId());
3821 }
3822 } else if (currentAction->getActionType() == CAction::E_AT_ASSIGN_FROM_SAMPLE) {
3823 double value = currentAction->getDistribution()->sample();
3824 M_callVariableTable->getVar(currentAction->getVarId())->setDouble(value);
3825 } else if (currentAction->getActionType() == CAction::E_AT_ASSIGN_FROM_STRING) {
3826 char* x = createSendingMessage(currentAction->getMessage(), -2 /* do not add crlf*/);
3827 char *str = strdup(x);
3828 if (!str) {
3829 ERROR("Out of memory duplicating string for assignment!");
3830 }
3831 M_callVariableTable->getVar(currentAction->getVarId())->setString(str);
3832 } else if (currentAction->getActionType() == CAction::E_AT_LOG_TO_FILE) {
3833 char* x = createSendingMessage(currentAction->getMessage(), -2 /* do not add crlf*/);
3834 LOG_MSG("%s\n", x);
3835 } else if (currentAction->getActionType() == CAction::E_AT_LOG_WARNING) {
3836 char* x = createSendingMessage(currentAction->getMessage(), -2 /* do not add crlf*/);
3837 WARNING("%s", x);
3838 } else if (currentAction->getActionType() == CAction::E_AT_LOG_ERROR) {
3839 char* x = createSendingMessage(currentAction->getMessage(), -2 /* do not add crlf*/);
3840 ERROR("%s", x);
3841 } else if (currentAction->getActionType() == CAction::E_AT_EXECUTE_CMD) {
3842 char* x = createSendingMessage(currentAction->getMessage(), -2 /* do not add crlf*/);
3843 // TRACE_MSG("Trying to execute [%s]", x);
3844 pid_t l_pid;
3845 switch(l_pid = fork()) {
3846 case -1:
3847 // error when forking !
3848 ERROR_NO("Forking error main");
3849 break;
3850
3851 case 0:
3852 // first child process - execute the command
3853 if((l_pid = fork()) < 0) {
3854 ERROR_NO("Forking error child");
3855 } else {
3856 if( l_pid == 0) {
3857 int ret;
3858 ret = system(x); // second child runs
3859 if(ret == -1) {
3860 WARNING("system call error for %s",x);
3861 }
3862 }
3863 exit(EXIT_OTHER);
3864 }
3865 break;
3866 default:
3867 // parent process continue
3868 // reap first child immediately
3869 pid_t ret;
3870 while ((ret=waitpid(l_pid, NULL, 0)) != l_pid) {
3871 if (ret != -1) {
3872 ERROR("waitpid returns %1d for child %1d",ret,l_pid);
3873 }
3874 }
3875 break;
3876 }
3877 } else if (currentAction->getActionType() == CAction::E_AT_EXEC_INTCMD) {
3878 switch (currentAction->getIntCmd()) {
3879 case CAction::E_INTCMD_STOP_ALL:
3880 quitting = 1;
3881 break;
3882 case CAction::E_INTCMD_STOP_NOW:
3883 sipp_exit(EXIT_TEST_RES_INTERNAL);
3884 break;
3885 case CAction::E_INTCMD_STOPCALL:
3886 default:
3887 return(call::E_AR_STOP_CALL);
3888 break;
3889 }
3890 #ifdef PCAPPLAY
3891 } else if ((currentAction->getActionType() == CAction::E_AT_PLAY_PCAP_AUDIO) ||
3892 (currentAction->getActionType() == CAction::E_AT_PLAY_PCAP_IMAGE) ||
3893 (currentAction->getActionType() == CAction::E_AT_PLAY_PCAP_VIDEO)) {
3894 play_args_t *play_args;
3895 if (currentAction->getActionType() == CAction::E_AT_PLAY_PCAP_AUDIO) {
3896 play_args = &(this->play_args_a);
3897 } else if (currentAction->getActionType() == CAction::E_AT_PLAY_PCAP_IMAGE) {
3898 play_args = &(this->play_args_i);
3899 } else if (currentAction->getActionType() == CAction::E_AT_PLAY_PCAP_VIDEO) {
3900 play_args = &(this->play_args_v);
3901 } else {
3902 ERROR("Can't find pcap data to play");
3903 }
3904
3905 play_args->pcap = currentAction->getPcapPkts();
3906 /* port number is set in [auto_]media_port interpolation */
3907 if (media_ip_is_ipv6) {
3908 struct sockaddr_in6 *from = (struct sockaddr_in6 *)(void *) &(play_args->from);
3909 from->sin6_family = AF_INET6;
3910 inet_pton(AF_INET6, media_ip, &(from->sin6_addr));
3911 } else {
3912 struct sockaddr_in *from = (struct sockaddr_in *)(void *) &(play_args->from);
3913 from->sin_family = AF_INET;
3914 from->sin_addr.s_addr = inet_addr(media_ip);
3915 }
3916 /* Create a thread to send RTP or UDPTL packets */
3917 pthread_attr_t attr;
3918 pthread_attr_init(&attr);
3919 #ifndef PTHREAD_STACK_MIN
3920 #define PTHREAD_STACK_MIN 16384
3921 #endif
3922 //pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
3923 if (media_thread != 0) {
3924 // If a media_thread is already active, kill it before starting a new one
3925 pthread_cancel(media_thread);
3926 pthread_join(media_thread, NULL);
3927 media_thread = 0;
3928 }
3929 int ret = pthread_create(&media_thread, &attr, send_wrapper,
3930 (void *) play_args);
3931 if(ret)
3932 ERROR("Can't create thread to send RTP packets");
3933 pthread_attr_destroy(&attr);
3934 #endif
3935
3936 #ifdef RTP_STREAM
3937 } else if (currentAction->getActionType() == CAction::E_AT_RTP_STREAM_PAUSE) {
3938 rtpstream_pause (&rtpstream_callinfo);
3939 } else if (currentAction->getActionType() == CAction::E_AT_RTP_STREAM_RESUME) {
3940 rtpstream_resume (&rtpstream_callinfo);
3941 } else if (currentAction->getActionType() == CAction::E_AT_RTP_STREAM_PLAY) {
3942 rtpstream_play (&rtpstream_callinfo,currentAction->getRTPStreamActInfo());
3943 #endif
3944 } else {
3945 ERROR("call::executeAction unknown action");
3946 }
3947 } // end for
3948 return(call::E_AR_NO_ERROR);
3949 }
3950
extractSubMessage(char * msg,char * matchingString,char * result,bool case_indep,int occurrence,bool headers)3951 void call::extractSubMessage(char * msg, char * matchingString, char* result, bool case_indep, int occurrence, bool headers)
3952 {
3953
3954 char *ptr, *ptr1;
3955 int sizeOf;
3956 int i = 0;
3957 int len = strlen(matchingString);
3958 char mat1 = tolower(*matchingString);
3959 char mat2 = toupper(*matchingString);
3960
3961 ptr = msg;
3962 while (*ptr) {
3963 if (!case_indep) {
3964 ptr = strstr(ptr, matchingString);
3965 if (ptr == NULL) break;
3966 if (headers == true && ptr != msg && *(ptr-1) != '\n') {
3967 ++ptr;
3968 continue;
3969 }
3970 } else {
3971 if (headers) {
3972 if (ptr != msg) {
3973 ptr = strchr(ptr, '\n');
3974 if (ptr == NULL) break;
3975 ++ptr;
3976 if (*ptr == 0) break;
3977 }
3978 } else {
3979 ptr1 = strchr(ptr, mat1);
3980 ptr = strchr(ptr, mat2);
3981 if (ptr == NULL) {
3982 if (ptr1 == NULL) break;
3983 ptr = ptr1;
3984 } else {
3985 if (ptr1 != NULL && ptr1 < ptr) ptr = ptr1;
3986 }
3987 }
3988 if (strncasecmp(ptr, matchingString, len) != 0) {
3989 ++ptr;
3990 continue;
3991 }
3992 }
3993 // here with ptr pointing to a matching string
3994 if (occurrence <= 1) break;
3995 --occurrence;
3996 ++ptr;
3997 }
3998
3999 if(ptr != NULL && *ptr != 0) {
4000 strncpy(result, ptr+len, MAX_SUB_MESSAGE_LENGTH);
4001 sizeOf = strlen(result);
4002 if(sizeOf >= MAX_SUB_MESSAGE_LENGTH)
4003 sizeOf = MAX_SUB_MESSAGE_LENGTH-1;
4004 while((i<sizeOf) && (result[i] != '\n') && (result[i] != '\r'))
4005 i++;
4006 result[i] = '\0';
4007 } else {
4008 result[0] = '\0';
4009 }
4010 }
4011
getFieldFromInputFile(const char * fileName,int field,SendingMessage * lineMsg,char * & dest)4012 void call::getFieldFromInputFile(const char *fileName, int field, SendingMessage *lineMsg, char*& dest)
4013 {
4014 if (m_lineNumber == NULL) {
4015 ERROR("Automatic calls (created by -aa, -oocsn or -oocsf) cannot use input files!");
4016 }
4017 if (inFiles.find(fileName) == inFiles.end()) {
4018 ERROR("Invalid injection file: %s", fileName);
4019 }
4020 int line = (*m_lineNumber)[fileName];
4021 if (lineMsg) {
4022 char lineBuffer[20];
4023 char *endptr;
4024 createSendingMessage(lineMsg, -2, lineBuffer, sizeof(lineBuffer));
4025 line = (int) strtod(lineBuffer, &endptr);
4026 if (*endptr != 0) {
4027 ERROR("Invalid line number generated: '%s'", lineBuffer);
4028 }
4029 if (line > inFiles[fileName]->numLines()) {
4030 line = -1;
4031 }
4032 }
4033 if (line < 0) {
4034 return;
4035 }
4036 dest += inFiles[fileName]->getField(line, field, dest, SIPP_MAX_MSG_SIZE);
4037 }
4038
checkAutomaticResponseMode(char * P_recv)4039 call::T_AutoMode call::checkAutomaticResponseMode(char * P_recv)
4040 {
4041 if (strcmp(P_recv, "BYE")==0) {
4042 return E_AM_UNEXP_BYE;
4043 } else if (strcmp(P_recv, "CANCEL") == 0) {
4044 return E_AM_UNEXP_CANCEL;
4045 } else if (strcmp(P_recv, "PING") == 0) {
4046 return E_AM_PING;
4047 } else if (auto_answer &&
4048 ((strcmp(P_recv, "INFO") == 0) ||
4049 (strcmp(P_recv, "NOTIFY") == 0) ||
4050 (strcmp(P_recv, "OPTIONS") == 0) ||
4051 (strcmp(P_recv, "UPDATE") == 0))) {
4052 return E_AM_AA;
4053 } else {
4054 return E_AM_DEFAULT;
4055 }
4056 }
4057
setLastMsg(const char * msg)4058 void call::setLastMsg(const char *msg)
4059 {
4060 realloc_ptr = (char *) realloc(last_recv_msg, strlen(msg) + 1);
4061 if (realloc_ptr) {
4062 last_recv_msg = realloc_ptr;
4063 } else {
4064 free(last_recv_msg);
4065 ERROR("Out of memory!");
4066 return;
4067 }
4068
4069 strcpy(last_recv_msg, msg);
4070 }
4071
automaticResponseMode(T_AutoMode P_case,char * P_recv)4072 bool call::automaticResponseMode(T_AutoMode P_case, char * P_recv)
4073 {
4074
4075 int res ;
4076 char * old_last_recv_msg = NULL;
4077 bool last_recv_msg_saved = false;
4078
4079 switch (P_case) {
4080 case E_AM_UNEXP_BYE: // response for an unexpected BYE
4081 // usage of last_ keywords
4082 realloc_ptr = (char *) realloc(last_recv_msg, strlen(P_recv) + 1);
4083 if (realloc_ptr) {
4084 last_recv_msg = realloc_ptr;
4085 } else {
4086 free(last_recv_msg);
4087 ERROR("Out of memory!");
4088 return false;
4089 }
4090
4091
4092 strcpy(last_recv_msg, P_recv);
4093
4094 // The BYE is unexpected, count it
4095 call_scenario->messages[msg_index] -> nb_unexp++;
4096 if (default_behaviors & DEFAULT_BEHAVIOR_ABORTUNEXP) {
4097 WARNING("Aborting call on an unexpected BYE for call: %s", (id==NULL)?"none":id);
4098 if (default_behaviors & DEFAULT_BEHAVIOR_BYE) {
4099 sendBuffer(createSendingMessage(get_default_message("200"), -1));
4100 }
4101
4102 // if twin socket call => reset the other part here
4103 if (twinSippSocket && (msg_index > 0)) {
4104 res = sendCmdBuffer(createSendingMessage(get_default_message("3pcc_abort"), -1));
4105 if (res) {
4106 WARNING("sendCmdBuffer returned %d", res);
4107 return false;
4108 }
4109 }
4110 computeStat(CStat::E_CALL_FAILED);
4111 computeStat(CStat::E_FAILED_UNEXPECTED_MSG);
4112 delete this;
4113 } else {
4114 WARNING("Continuing call on an unexpected BYE for call: %s", (id==NULL)?"none":id);
4115 }
4116 break ;
4117
4118 case E_AM_UNEXP_CANCEL: // response for an unexpected cancel
4119 // usage of last_ keywords
4120 realloc_ptr = (char *) realloc(last_recv_msg, strlen(P_recv) + 1);
4121 if (realloc_ptr) {
4122 last_recv_msg = realloc_ptr;
4123 } else {
4124 free(last_recv_msg);
4125 ERROR("Out of memory!");
4126 return false;
4127 }
4128
4129
4130 strcpy(last_recv_msg, P_recv);
4131
4132 // The CANCEL is unexpected, count it
4133 call_scenario->messages[msg_index] -> nb_unexp++;
4134 if (default_behaviors & DEFAULT_BEHAVIOR_ABORTUNEXP) {
4135 WARNING("Aborting call on an unexpected CANCEL for call: %s", (id==NULL)?"none":id);
4136 if (default_behaviors & DEFAULT_BEHAVIOR_BYE) {
4137 sendBuffer(createSendingMessage(get_default_message("200"), -1));
4138 }
4139
4140 // if twin socket call => reset the other part here
4141 if (twinSippSocket && (msg_index > 0)) {
4142 res = sendCmdBuffer(createSendingMessage(get_default_message("3pcc_abort"), -1));
4143 if (res) {
4144 WARNING("sendCmdBuffer returned %d", res);
4145 return false;
4146 }
4147 }
4148
4149 computeStat(CStat::E_CALL_FAILED);
4150 computeStat(CStat::E_FAILED_UNEXPECTED_MSG);
4151 delete this;
4152 } else {
4153 WARNING("Continuing call on unexpected CANCEL for call: %s", (id==NULL)?"none":id);
4154 }
4155 break ;
4156
4157 case E_AM_PING: // response for a random ping
4158 // usage of last_ keywords
4159 realloc_ptr = (char *) realloc(last_recv_msg, strlen(P_recv) + 1);
4160 if (realloc_ptr) {
4161 last_recv_msg = realloc_ptr;
4162 } else {
4163 free(last_recv_msg);
4164 ERROR("Out of memory!");
4165 return false;
4166 }
4167
4168
4169 strcpy(last_recv_msg, P_recv);
4170
4171 if (default_behaviors & DEFAULT_BEHAVIOR_PINGREPLY) {
4172 WARNING("Automatic response mode for an unexpected PING for call: %s", (id==NULL)?"none":id);
4173 sendBuffer(createSendingMessage(get_default_message("200"), -1));
4174 // Note: the call ends here but it is not marked as bad. PING is a
4175 // normal message.
4176 // if twin socket call => reset the other part here
4177 if (twinSippSocket && (msg_index > 0)) {
4178 res = sendCmdBuffer(createSendingMessage(get_default_message("3pcc_abort"), -1));
4179 if (res) {
4180 WARNING("sendCmdBuffer returned %d", res);
4181 return false;
4182 }
4183 }
4184
4185 CStat::globalStat(CStat::E_AUTO_ANSWERED);
4186 delete this;
4187 } else {
4188 WARNING("Do not answer on an unexpected PING for call: %s", (id==NULL)?"none":id);
4189 }
4190 break ;
4191
4192 case E_AM_AA: // response for a random INFO, NOTIFY, OPTIONS or UPDATE
4193 // store previous last msg if msg is INFO, NOTIFY, OPTIONS or UPDATE
4194 // restore last_recv_msg to previous one
4195 // after sending ok
4196 old_last_recv_msg = NULL;
4197 if (last_recv_msg != NULL) {
4198 last_recv_msg_saved = true;
4199 old_last_recv_msg = (char *) malloc(strlen(last_recv_msg)+1);
4200 strcpy(old_last_recv_msg,last_recv_msg);
4201 }
4202 // usage of last_ keywords
4203 realloc_ptr = (char *) realloc(last_recv_msg, strlen(P_recv) + 1);
4204 if (realloc_ptr) {
4205 last_recv_msg = realloc_ptr;
4206 } else {
4207 free(last_recv_msg);
4208 free(old_last_recv_msg);
4209 ERROR("Out of memory!");
4210 return false;
4211 }
4212
4213
4214 strcpy(last_recv_msg, P_recv);
4215
4216 WARNING("Automatic response mode for an unexpected INFO, NOTIFY, OPTIONS or UPDATE for call: %s",
4217 (id == NULL) ? "none" : id);
4218 sendBuffer(createSendingMessage(get_default_message("200"), -1));
4219
4220 // restore previous last msg
4221 if (last_recv_msg_saved == true) {
4222 realloc_ptr = (char *) realloc(last_recv_msg, strlen(old_last_recv_msg) + 1);
4223 if (realloc_ptr) {
4224 last_recv_msg = realloc_ptr;
4225 } else {
4226 free(last_recv_msg);
4227 ERROR("Out of memory!");
4228 return false;
4229 }
4230
4231
4232 strcpy(last_recv_msg, old_last_recv_msg);
4233 if (old_last_recv_msg != NULL) {
4234 free(old_last_recv_msg);
4235 old_last_recv_msg = NULL;
4236 }
4237 }
4238 CStat::globalStat(CStat::E_AUTO_ANSWERED);
4239 return true;
4240 break;
4241
4242 default:
4243 ERROR("Internal error for automaticResponseMode - mode %d is not implemented!", P_case);
4244 break ;
4245 }
4246
4247 return false;
4248 }
4249
4250 #ifdef PCAPPLAY
send_wrapper(void * arg)4251 void *send_wrapper(void *arg)
4252 {
4253 play_args_t *s = (play_args_t *) arg;
4254 //struct sched_param param;
4255 //int ret;
4256 //param.sched_priority = 10;
4257 //ret = pthread_setschedparam(pthread_self(), SCHED_RR, ¶m);
4258 //if(ret)
4259 // ERROR("Can't set RTP play thread realtime parameters");
4260 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
4261 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
4262 send_packets(s);
4263 pthread_exit(NULL);
4264 return NULL;
4265 }
4266 #endif
4267