📄 call.cpp
字号:
if(call_socket) { state = &comp_state; sock = call_socket; } else { state = &monosocket_comp_state; if(transport == T_UDP) { sock = main_socket; } else { sock = tcp_multiplex; } } rc = send_message(sock, state, msg); if(rc == -1) return -1; if(rc < -1) { CStat::instance()->computeStat(CStat::E_CALL_FAILED); CStat::instance()->computeStat(CStat::E_FAILED_CANNOT_SEND_MSG); delete_call(id); } return rc; /* OK */}char * call::compute_cseq(char * src){ char *dest; static char cseq[MAX_HEADER_LEN * 10]; if(dest = strstr(src, "CSeq")) { /* If we find a CSeq in incoming msg */ char * last_header = get_last_header(dest+4); if(last_header) { int i; /* Extract the integer value of the last CSeq */ last_header = strstr(last_header, ":"); last_header++; while(isspace(*last_header)) last_header++; sscanf(last_header,"%d", &i); /* Add 1 to the last CSeq value */ sprintf(cseq, "%s%d", "CSeq: ", (i+1)); } else { sprintf(cseq, "%s", "CSeq: 2"); } return cseq; } else { return NULL; }}char * call::get_last_header(char * name){ static char last_header[MAX_HEADER_LEN * 10]; char * src, *dest, *ptr; char src_tmp[1024] = "\n"; if((!last_recv_msg) || (!strlen(last_recv_msg))) { return NULL; } src = last_recv_msg; dest = last_header; strcpy(src_tmp+1,name); while(src = strcasestr2(src, src_tmp)) { src++; ptr = strchr(src, '\n'); /* Multiline headers always begin with a tab or a space * on the subsequent lines */ while((ptr) && ((*(ptr+1) == ' ' ) || (*(ptr+1) == '\t') )) { ptr = strchr(ptr + 1, '\n'); } if(ptr) { *ptr = 0; } // Add \r\n when several Via header are present (AgM) if (dest != last_header) { dest += sprintf(dest, "\r\n"); } dest += sprintf(dest, "%s", src); if(ptr) { *ptr = '\n'; } src++; } if(dest == last_header) { return NULL; } *(dest--) = 0; /* Remove trailing whitespaces, tabs, and CRs */ while ((dest > last_header) && ((*dest == ' ') || (*dest == '\r')|| (*dest == '\t'))) { *(dest--) = 0; } /* remove enclosed CRs in multilines */ /* don't remove enclosed CRs for multiple headers (e.g. Via) (Rhys) */ while((ptr = strstr(last_header, "\r\n")) != NULL && ( *(ptr + 2) == ' ' || *(ptr + 2) == '\r' || *(ptr + 2) == '\t') ) { /* Use strlen(ptr) to include trailing zero */ memmove(ptr, ptr+1, strlen(ptr)); } /* Remove illegal double CR characters */ while((ptr = strstr(last_header, "\r\r")) != NULL) { memmove(ptr, ptr+1, strlen(ptr)); } /* Remove illegal double Newline characters */ while((ptr = strstr(last_header, "\n\n")) != NULL) { memmove(ptr, ptr+1, strlen(ptr)); } return last_header;}char * call::get_header_content(char* message, char * name){ /* non reentrant. consider accepting char buffer as param */ static char last_header[MAX_HEADER_LEN * 10]; char * src, *dest, *ptr; /* returns empty string in case of error */ memset(last_header, 0, sizeof(last_header)); if((!message) || (!strlen(message))) { return last_header; } src = message; dest = last_header; /* for safety's sake */ if (NULL == name || NULL == strrchr(name, ':')) { return last_header; } while(src = strstr(src, name)) { /* just want the header's content */ src += strlen(name); ptr = strchr(src, '\n'); /* Multiline headers always begin with a tab or a space * on the subsequent lines */ while((ptr) && ((*(ptr+1) == ' ' ) || (*(ptr+1) == '\t') )) { ptr = strchr(ptr + 1, '\n'); } if(ptr) { *ptr = 0; } // Add "," when several headers are present if (dest != last_header) { dest += sprintf(dest, ","); } dest += sprintf(dest, "%s", src); if(ptr) { *ptr = '\n'; } src++; } if(dest == last_header) { return last_header; } *(dest--) = 0; /* Remove trailing whitespaces, tabs, and CRs */ while ((dest > last_header) && ((*dest == ' ') || (*dest == '\r')|| (*dest == '\t'))) { *(dest--) = 0; } /* remove enclosed CRs in multilines */ while(ptr = strchr(last_header, '\r')) { /* Use strlen(ptr) to include trailing zero */ memmove(ptr, ptr+1, strlen(ptr)); } return last_header;}char * call::send_scene(int index, int *send_status){ static char msg_buffer[SIPP_MAX_MSG_SIZE];#define MAX_MSG_NAME_SIZE 30 static char msg_name[MAX_MSG_NAME_SIZE]; char *L_ptr1 ; char *L_ptr2 ; /* Socket port must be known before string substitution */ connect_socket_if_needed(); if(scenario[index] -> send_scheme) { char * dest; dest = createSendingMessage(scenario[index] -> send_scheme, index); strcpy(msg_buffer, dest); if (dest) { L_ptr1=msg_name ; L_ptr2=msg_buffer ; while ((*L_ptr2 != ' ') && (*L_ptr2 != '\n') && (*L_ptr2 != '\t')) { *L_ptr1 = *L_ptr2; L_ptr1 ++; L_ptr2 ++; } *L_ptr1 = '\0' ; } if (strcmp(msg_name,"ACK") == 0) { call_established = true ; ack_is_pending = false ; } if(send_status) { *send_status = send_raw(msg_buffer, index); } else { send_raw(msg_buffer, index); } } else { ERROR("Unsupported 'send' message in scenario"); } return msg_buffer;}bool call::next(){ int test = scenario[msg_index]->test; /* What is the next message index? */ if ( scenario[msg_index]->next && ((test == -1) || (test < SCEN_VARIABLE_SIZE && M_callVariableTable[test] != NULL && M_callVariableTable[test]->isSet())) ) { /* For branching, use the 'next' attribute value */ msg_index = labelArray[scenario[msg_index]->next]; } else { /* Without branching, use the next message */ msg_index++; } if(msg_index >= scenario_len) { // Call end -> was it successful? if(call::last_action_result != call::E_AR_NO_ERROR) { switch(call::last_action_result) { case call::E_AR_REGEXP_DOESNT_MATCH: CStat::instance()->computeStat(CStat::E_CALL_FAILED); CStat::instance()->computeStat(CStat::E_FAILED_REGEXP_DOESNT_MATCH); break; case call::E_AR_HDR_NOT_FOUND: CStat::instance()->computeStat(CStat::E_CALL_FAILED); CStat::instance()->computeStat(CStat::E_FAILED_REGEXP_HDR_NOT_FOUND); break; } } else { CStat::instance()->computeStat(CStat::E_CALL_SUCCESSFULLY_ENDED); } delete_call(id); return false; } return run();}bool call::run(){ if(msg_index >= scenario_len) { ERROR_P3("Scenario overrun for call %s (%08x) (index = %d)\n", id, this, msg_index); } /* Manages retransmissions or delete if max retrans reached */ if(next_retrans && (next_retrans < clock_tick)) { nb_retrans++; if(nb_retrans > UDP_MAX_RETRANS) { scenario[last_send_index] -> nb_timeout ++; CStat::instance()->computeStat(CStat::E_CALL_FAILED); CStat::instance()->computeStat(CStat::E_FAILED_MAX_UDP_RETRANS); if (default_behavior) { // Abort the call by sending proper SIP message WARNING_P1("Aborting call on UDP retransmission timeout for Call-ID '%s'", id); return(abortCall()); } else { // Just delete existing call delete_call(id); return false; } } else { unsigned int delay = scenario[last_send_index] -> retrans_delay; unsigned int pow = nb_retrans; while(pow--) { delay *= 2; } if(send_raw(last_send_msg, last_send_index) < -1) { return false; } scenario[last_send_index] -> nb_sent_retrans++; next_retrans = clock_tick + delay; } } if(paused_until) { /* Process a pending pause instruction until delay expiration */ if(paused_until > clock_tick) { return true; } else { paused_until = 0; return next(); } } else if(scenario[msg_index] -> pause) { /* Starts a pause instruction */ if((scenario[msg_index] -> pause) && ((scenario[msg_index] -> pause) == -1)) { paused_until = clock_tick + duration; } else { paused_until = clock_tick + scenario[msg_index] -> pause; } return run(); /* In case delay is 0 */ } #ifdef __3PCC__ else if(scenario[msg_index] -> M_type == MSG_TYPE_SENDCMD) { int send_status; if(next_retrans) { return true; } send_status = sendCmdMessage(msg_index); if(send_status != 0) { /* Send error */ return false; /* call deleted */ } scenario[msg_index] -> M_nbCmdSent++; next_retrans = 0; return(next()); }#endif else if(scenario[msg_index] -> send_scheme) { char * msg_snd; int send_status; /* Do not send a new message until the previous one which had * retransmission enabled is acknowledged */ if(next_retrans) { return true; } /* If this message can be used to compute RTD, do it now */ if(!rtd_done) { if(scenario[msg_index] -> start_rtd) { start_time_rtd = clock_tick; } if(scenario[msg_index] -> stop_rtd) { rtd_sum += clock_tick - start_time_rtd; CStat::instance()->computeStat(CStat::E_ADD_RESPONSE_TIME_DURATION, clock_tick - start_time_rtd); rtd_nb ++; rtd_done = true; } } msg_snd = send_scene(msg_index, &send_status); if(send_status == -1) { /* Would Block on TCP */ return true; /* No step, nothing done, retry later */ } if(send_status <-1) { /* Send error */ return false; /* call deleted */ } last_send_index = msg_index; last_send_msg = (char *) realloc(last_send_msg, strlen(msg_snd) + 1); strcpy(last_send_msg, msg_snd); if(last_recv_hash) { /* We are sending just after msg reception. There is a great * chance that we will be asked to retransmit this message */ recv_retrans_hash = last_recv_hash; recv_retrans_recv_index = last_recv_index; recv_retrans_send_index = msg_index; /* Prevent from detecting the cause relation between send and recv * in the next valid send */ last_recv_hash = 0; } /* Update retransmission information */ if(scenario[msg_index] -> retrans_delay) { if((transport == T_UDP) && (retrans_enabled)) { next_retrans = clock_tick + scenario[msg_index] -> retrans_delay; nb_retrans = 0; } } else { next_retrans = 0; } /* Update scenario statistics */ scenario[msg_index] -> nb_sent++; return next(); } return true;}bool call::process_unexpected(char * msg){ int search_index; static int first = 1; int res ; scenario[msg_index] -> nb_unexp++; if (scenario[msg_index] -> recv_request) { if (default_behavior) { WARNING_P3("Aborting call on unexpected message for Call-ID '%s': while expecting '%s', received '%s' ", id, scenario[msg_index] -> recv_request, msg); } else { WARNING_P3("Continuing call on unexpected message for Call-ID '%s': while expecting '%s', received '%s' ", id, scenario[msg_index] -> recv_request, msg); } } else { if (default_behavior) { WARNING_P3("Aborting call on unexpected message for Call-ID '%s': while expecting '%d' response, received '%s' ", id, scenario[msg_index] -> recv_response, msg); } else { WARNING_P3("Continuing call on unexpected message for Call-ID '%s': while expecting '%d' response, received '%s' ", id, scenario[msg_index] -> recv_response, msg);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -