📄 call.cpp
字号:
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(){ 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 ++; TRACE_TIMEOUT((s, "Timeout for call id: %s\n", id)); CStat::instance()->computeStat(CStat::E_CALL_FAILED); CStat::instance()->computeStat(CStat::E_FAILED_MAX_UDP_RETRANS); 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) { WARNING_P3("Unexpected message for Call-ID '%s': while expecting '%s', received '%s' ", id, scenario[msg_index] -> recv_request, msg); } else { WARNING_P3("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)); #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); return (abortCall());}bool call::abortCall(){ int res ; if ((toolMode != MODE_SERVER) && (msg_index > 0)) { if (call_established == false) { char * src = 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(get_reply_code(src) > 400) { sendBuffer(createSendingMessage( (char*)"ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n" "Via: SIP/2.0/[transport] [local_ip]:[local_port]\n" "From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]\n" "To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]\n" "Call-ID: [call_id]\n" "Cseq: 1 ACK\n" "Contact: sip:sipp@[local_ip]:[local_port]\n" "Max-Forwards: 70\n" "Subject: Performance Test\n" "Content-Length: 0\n\n" , -1)); } else { /* Call is not established and the reply is not a 4XX, 5XX */ if (ack_is_pending == true) { /* 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, "[last_Via:]\n"); sprintf(L_param, "%s%s", L_param, "[last_From:]\n"); sprintf(L_param, "%s%s", L_param, "[last_To:]\n"); sprintf(L_param, "%s%s", L_param, "[last_Call-ID:]\n"); /* The CSeq of an ACK relating to an INVITE must be the same as */ /* the one from the INVITE. */ /* Let's simplify this by putting 1 (no support for re-invite in */ /* 3PCC?) */ /* FIXME: store CSeq from last INVITE and re-use it */ sprintf(L_param, "%sCSeq: 1 ACK\n", L_param); 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 */ strcpy(L_param, "BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"); sprintf(L_param, "%s%s", L_param, "[last_Via:]\n"); sprintf(L_param, "%s%s", L_param, "[last_From:]\n"); sprintf(L_param, "%s%s", L_param, "[last_To:]\n"); sprintf(L_param, "%s%s", L_param, "[last_Call-ID:]\n"); char * cseq; cseq = compute_cseq(src); if (cseq != NULL) { sprintf(L_param, "%s%s BYE\n", L_param, compute_cseq(src)); } 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)); } else { /* Send a CANCEL */ strcpy(L_param, "CANCEL sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"); sprintf(L_param, "%s%s", L_param, "[last_Via:]\n"); sprintf(L_param, "%s%s", L_param, "[last_From:]\n"); sprintf(L_param, "%s%s", L_param, "[last_To:]\n"); sprintf(L_param, "%s%s", L_param, "[last_Call-ID:]\n"); char * cseq; cseq = compute_cseq(src); if (cseq != NULL) { sprintf(L_param, "%s%s CANCEL\n", L_param, compute_cseq(src)); } 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)); } } } else { /* Call is established */ char * src = last_recv_msg ; char L_msg_buffer[SIPP_MAX_MSG_SIZE]; L_msg_buffer[0] = '\0'; char * L_param = L_msg_buffer; strcpy(L_param, "BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0\n"); sprintf(L_param, "%s%s", L_param, "[last_Via:]\n"); sprintf(L_param, "%s%s", L_param, "[last_From:]\n"); sprintf(L_param, "%s%s", L_param, "[last_To:]\n"); sprintf(L_param, "%s%s", L_param, "[last_Call-ID:]\n"); char * cseq; cseq = compute_cseq(src); if (cseq != NULL) { sprintf(L_param, "%s%s BYE\n", L_param, compute_cseq(src)); } 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)); } } CStat::instance()->computeStat(CStat::E_CALL_FAILED); CStat::instance()->computeStat(CStat::E_FAILED_UNEXPECTED_MSG); delete_call(id); return false;}bool call::rejectCall(){ CStat::instance()->computeStat(CStat::E_CALL_FAILED); CStat::instance()->computeStat(CStat::E_FAILED_CALL_REJECTED); delete_call(id); return false;}#ifdef __3PCC__int call::sendCmdMessage(int index){ char * dest; char delimitor[2]; delimitor[0]=27; delimitor[1]=0; if(scenario[index] -> M_sendCmdData) { // WARNING_P1("---PREPARING_TWIN_CMD---%s---", scenario[index] -> M_sendCmdData); dest = createSendingMessage(scenario[index] -> M_sendCmdData, -2); strcat(dest, delimitor); //WARNING_P1("---SEND_TWIN_CMD---%s---", dest); int rc; rc = send(twinSippSocket, dest,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -