📄 call.cpp
字号:
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++; } recv_timeout = 0; 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(){ bool bInviteTransaction = false; int actionResult = 0; assert(running); 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 ? max_invite_retrans : max_non_invite_retrans)) || (nb_retrans > max_udp_retrans)) { scenario[last_send_index] -> nb_timeout ++; if (scenario[last_send_index]->on_timeout) { // action on timeout WARNING_P3("Call-Id: %s, timeout on max UDP retrans for message %d, jumping to label %d ", id, msg_index, scenario[last_send_index]->on_timeout); msg_index = labelArray[scenario[last_send_index]->on_timeout]; next_retrans = 0; recv_timeout = 0; if (msg_index < scenario_len) return true; // here if asked to go to the last label delete the call 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 return(abortCall()); } else { // Just delete existing call delete_call(id); return false; } } 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++; CStat::instance()->computeStat(CStat::E_RETRANSMISSION); next_retrans = clock_tick + nb_last_delay; } } if(paused_until) { /* Process a pending pause instruction until delay expiration */ if(paused_until > clock_tick) { if (!remove_running_call(this)) { ERROR("Tried to remove a running call that wasn't running!\n"); } paused_calls.add_paused_call(this, true); return true; } /* Our pause is over. */ paused_until = 0; return next(); } else if(scenario[msg_index] -> pause_function) { unsigned int pause; pause = scenario[msg_index] -> pause_function(scenario[msg_index]); if (pause > INT_MAX) { pause = INT_MAX; } paused_until = clock_tick + pause; /* 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) { do_bookkeeping(msg_index); 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) { if (!remove_running_call(this)) { ERROR("Tried to remove a running call that wasn't running!\n"); } paused_calls.add_paused_call(this, true); return true; } /* Handle counters and RTDs for this message. */ do_bookkeeping(msg_index); /* 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 */ int incr_cseq = 0; 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; incr_cseq = 1; } 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 (incr_cseq) --cseq; return true; /* No step, nothing done, retry later */ } else 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(); } else if (scenario[msg_index]->M_type == MSG_TYPE_RECV#ifdef __3PCC__ || scenario[msg_index]->M_type == MSG_TYPE_RECVCMD#endif ) { if (recv_timeout) { if(recv_timeout > clock_tick || recv_timeout > getmilliseconds()) { if (!remove_running_call(this)) { ERROR("Tried to remove a running call that wasn't running!\n"); } paused_calls.add_paused_call(this, true); return true; } recv_timeout = 0; ++scenario[msg_index]->nb_timeout; if (scenario[msg_index]->on_timeout == 0) { // if you set a timeout but not a label, the call is aborted WARNING_P2("Call-Id: %s, receive timeout on message %d without label to jump to (ontimeout attribute): aborting call", id, msg_index); CStat::instance()->computeStat(CStat::E_CALL_FAILED); CStat::instance()->computeStat(CStat::E_FAILED_TIMEOUT_ON_RECV); if (default_behavior) { return (abortCall()); } else { delete_call(id); return false; } } WARNING_P3("Call-Id: %s, receive timeout on message %d, jumping to label %d", id, msg_index, scenario[msg_index]->on_timeout); msg_index = labelArray[scenario[msg_index]->on_timeout]; recv_timeout = 0; if (msg_index < scenario_len) return true; // special case - the label points to the end - finish the call CStat::instance()->computeStat(CStat::E_CALL_FAILED); CStat::instance()->computeStat(CStat::E_FAILED_TIMEOUT_ON_RECV); if (default_behavior) { return (abortCall()); } else { delete_call(id); return false; } } else if ((scenario[msg_index]->retrans_delay) || (defl_recv_timeout)) { if (scenario[msg_index]->retrans_delay) // If timeout is specified on message receive, use it recv_timeout = getmilliseconds() + scenario[msg_index]->retrans_delay; else // Else use the default timeout if specified recv_timeout = getmilliseconds() + defl_recv_timeout; return true; } else { /* We are going to wait forever. */ if (!remove_running_call(this)) { ERROR("Tried to remove a running call that wasn't running!\n"); } paused_calls.add_paused_call(this, true); } } 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); CStat::instance()->computeStat(CStat::E_FAILED_UNEXPECTED_MSG); return (abortCall()); } else { // Do not abort call nor send anything in reply if default behavior is disabled return false; }}bool call::abortCall(){ int res ; int is_inv; char * src_send = NULL ; char * src_recv = NULL ; if (last_send_msg != NULL) { is_inv = !strncmp(last_send_msg, "INVITE", 6); } else { is_inv = false; } if ((toolMode != MODE_SERVER) && (msg_index > 0)) { if ((call_established == false) && (is_inv)) { src_recv = last_recv_msg ; char * dest ; char L_msg_buffer[SIPP_MAX_MSG_SIZE]; L_msg_buffer[0] = '\0'; char * L_param = L_msg_buffer; // Answer unexpected errors (4XX, 5XX and beyond) with an ACK // Contributed by F. Tarek Rogers if((src_recv) && (get_reply_code(src_recv) >= 400)) { strcpy(L_param, "ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"); sprintf(L_param, "%s%s", L_param, "Via: SIP/2.0/[transport] [local_ip]:[local_port]\n"); sprintf(L_param, "%s%s", L_param, "From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]\n"); sprintf(L_param, "%s%s", L_param, "To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n"); sprintf(L_param, "%s%s", L_param, "Call-ID: [call_id]\n"); char * cseq; cseq = get_header_field_code(src_recv,(char *) "CSeq:"); if (cseq != NULL) { sprintf(L_param, "%s%s ACK\n", L_param, cseq); } sprintf(L_param, "%s%s", L_param, "Contact: <sip:sipp@[local_ip]:[local_port];transport=[transport]>\n"); sprintf(L_param, "%s%s", L_param, "Max-Forwards: 70\n"); sprintf(L_param, "%s%s", L_param, "Subject: Performance Test\n"); sprintf(L_param, "%s%s", L_param, "Content-Length: 0\n"); res = sendBuffer(createSendingMessage((char*)(L_param),-1)); } else if (src_recv) { /* Call is not established and the reply is not a 4XX, 5XX */ /* And we already received a message. */ if (ack_is_pending == true) { char * cseq = NULL; /* If an ACK is expected from the other side, send it * and send a BYE afterwards */ ack_is_pending = false; /* Send an ACK */ strcpy(L_param, "ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"); sprintf(L_param, "%s%s", L_param, "Via: SIP/2.0/[transport] [local_ip]:[local_port]\n"); sprintf(L_param, "%s%s", L_param, "From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]\n"); sprintf(L_param, "%s%s", L_param, "To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n"); sprintf(L_param, "%s%s", L_param, "Call-ID: [call_id]\n"); src_send = last_send_msg ; cseq = get_header_field_code(src_recv,"CSeq:"); if (cseq != NULL) { sprintf(L_param, "%s%s ACK\n", L_param, cseq); } sprintf(L_param, "%s%s", L_param, "Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"); sprintf(L_param, "%s%s", L_param, "Content-Length: 0\n"); res = sendBuffer(createSendingMessage((char*)(L_param),-1)); /* Send the BYE */ cseq = NULL; strcpy(L_param, "BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"); sprintf(L_param, "%s%s", L_param, "Via: SIP/2.0/[transport] [local_ip]:[local_port]\n"); sprintf(L_param, "%s%s", L_param, "From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]\n"); sprintf(L_param, "%s%s", L_param, "To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n"); sprintf(L_param, "%s%s", L_param, "Call-ID: [call_id]\n"); cseq = compute_cseq(src_recv); if (cseq != NULL) { sprintf(L_param, "%s%s BYE\n", L_param, compute_cseq(src_recv)); } sprintf(L_param, "%s%s", L_param, "Contact: <sip:[local_ip]:[local_port];transport=[transport]>\n"); sprintf(L_param, "%s%s", L_param, "Content-Length: 0\n"); res = sendBuffer(createSendingMessage((char*)(L_param),-1));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -