📄 call.cpp
字号:
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 = strcasestr2(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 leading whitespaces */ while (*last_header == ' ') { strcpy(last_header, &last_header[1]); } /* 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(){ struct timeval L_currentTime ; double L_stop_time ; bool bInviteTransaction = false; int actionResult = 0; 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 ( (0 == strncmp (last_send_msg, "INVITE", 6)) ) { bInviteTransaction = true; } if((nb_retrans > (bInviteTransaction ? UDP_MAX_RETRANS_INVITE_TRANSACTION : UDP_MAX_RETRANS_NON_INVITE_TRANSACTION)) || (nb_retrans > max_udp_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 { nb_last_delay *= 2; if (DEFAULT_T2_TIMER_VALUE < nb_last_delay) { if (!bInviteTransaction) { nb_last_delay = DEFAULT_T2_TIMER_VALUE; } } if(send_raw(last_send_msg, last_send_index) < -1) { return false; } scenario[last_send_index] -> nb_sent_retrans++; next_retrans = clock_tick + nb_last_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) == -1) { paused_until = clock_tick + duration; } else { paused_until = clock_tick + scenario[msg_index] -> pause; } /* Increment the number of sessions in pause state */ ++scenario[msg_index]->sessions; return run(); /* In case delay is 0 */ } else if(scenario[msg_index] -> pause_max) { /* Starts a variable pause instruction */ paused_until = clock_tick + scenario[msg_index] -> pause_min + rand() % (scenario[msg_index] -> pause_max - scenario[msg_index] -> pause_min); /* Increment the number of sessions in pause state */ ++scenario[msg_index]->sessions; 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] -> M_type == MSG_TYPE_NOP) { actionResult = executeAction(NULL, msg_index); return(next()); } 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; if(dumpInRtt) { GET_TIME (&L_currentTime); L_stop_time = (double)L_currentTime.tv_sec*1000.0 + (double)(L_currentTime.tv_usec)/(double)1000.0 ; CStat::instance()->computeRtt(start_time_rtd, L_stop_time) ; } CStat::instance()->computeStat(CStat::E_ADD_RESPONSE_TIME_DURATION, clock_tick - start_time_rtd); rtd_nb ++; rtd_done = true; } } /* decide whether to increment cseq or not * basically increment for anything except response, ACK or CANCEL * Note that cseq is only used by the [cseq] keyword, and * not by default */ if (strncmp(::scenario[msg_index]->send_scheme,"ACK",3) && strncmp(::scenario[msg_index]->send_scheme,"CANCEL",6) && strncmp(::scenario[msg_index]->send_scheme,"SIP/2.0",7)) { ++cseq; } if ((ctrlEW) || (poll_flag_write)) { send_status = -1; } else { msg_snd = send_scene(msg_index, &send_status); } if(send_status == -1) { /* Would Block on TCP */ if (msg_index == 0 ) delete_call(id) ; 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; nb_last_delay = scenario[msg_index]->retrans_delay; } } else { next_retrans = 0; } #ifdef PCAPPLAY actionResult = executeAction(msg_snd, msg_index);#endif /* 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); } } TRACE_MSG((s, "-----------------------------------------------\n" "Unexpected %s message received:\n\n%s\n", TRANSPORT_TO_STRING(transport), msg)); if (default_behavior) {#ifdef __3PCC__ // if twin socket call => reset the other part here if (twinSippSocket && (msg_index > 0)) { //WARNING_P2("call-ID '%s', internal-cmd: abort_call %s",id, ""); res = sendCmdBuffer (createSendingMessage((char*)"call-id: [call_id]\ninternal-cmd: abort_call\n", -1)); }#endif /* __3PCC__ */ // usage of last_ keywords => for call aborting last_recv_msg = (char *) realloc(last_recv_msg, strlen(msg) + 1); strcpy(last_recv_msg, msg); CStat::instance()->computeStat(CStat::E_CALL_FAILED);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -