📄 call.cpp
字号:
/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author : Richard GAYRAUD - 04 Nov 2003 * From Hewlett Packard Company. * Shriram Natarajan [snatarajan@longboard.com] */#include "sipp.hpp"#include <iterator>#include <algorithm>#include <fstream>#include <iostream>call_map calls;/************** Call map and management routines **************/call_map * get_calls(){ return & calls;}static unsigned int next_number = 1;call * add_call(char * call_id){ call * new_call; new_call = new call(call_id); if(!new_call) { ERROR("Memory Overflow"); } calls[std::string(call_id)] = new_call; if(!next_number) { next_number ++; } new_call -> number = next_number; /* Vital counters update */ next_number++; open_calls++; /* Statistics update */ calls_since_last_rate_change++; total_calls ++; if(open_calls > open_calls_peak) { open_calls_peak = open_calls; open_calls_peak_time = clock_tick / 1000; } return new_call;}call * add_call(){ static char call_id[MAX_HEADER_LEN]; call * new_call; if(!next_number) { next_number ++; } sprintf(call_id, "%u.%u.%s@sipp.call.id", next_number, pid, local_ip); return add_call(call_id);}call * get_call(char * call_id){ call * call_ptr; call_ptr = calls[std::string(call_id)]; if(!call_ptr) { calls.erase(std::string(call_id)); } return call_ptr;}void delete_call(char * call_id){ call * call_ptr = calls[std::string(call_id)]; if(!calls.erase(std::string(call_id))) { ERROR("Call not erased from map"); } if(call_ptr) { delete call_ptr; open_calls--; } else { ERROR("Call not found"); }}/******* Very simple hash for retransmission detection *******/unsigned long hash(char * msg) { unsigned long rv = 0; int len = strlen(msg); int index = 0; if (len > 4) { rv = msg[0] + msg[1] + msg[2] + msg[3]; } if (len > 12) { rv += msg[9] + msg[10] + msg[11] + msg[12]; } rv <<= 8; rv += len; rv <<= 16; for (index = 0; index < len; index ++) { rv += + msg[index] * index; } return rv;}/******************* Call class implementation ****************/call::InputFileUsage call::m_usage = call::InputFileSequentialOrder;int call::m_counter = 0;call::call(char * p_id) { memset(this, 0, sizeof(call)); id = strdup(p_id); start_time = clock_tick; call_established=false ; count_in_stats=true ; ack_is_pending=false ; // initialising the CallVariable with the Scenario variable for(int i=0; i<SCEN_VARIABLE_SIZE; i++) { if(scenVariableTable[i] != NULL) { M_callVariableTable[i] = new CCallVariable(); if (M_callVariableTable[i] == NULL) { ERROR ("call variable allocation failed"); } } else { M_callVariableTable[i] = NULL; } } // If not updated by a message we use the start time // information to compute rtd information start_time_rtd = clock_tick; // by default, last action result is NO_ERROR last_action_result = call::E_AR_NO_ERROR; if (InputFileRandomOrder == m_usage) { m_localLineNumber = rand() % numLinesInFile; } else { m_localLineNumber = m_counter++; if (m_counter >= numLinesInFile) { m_counter = 0; } } peer_tag[0] = '\0';}call::~call(){ deleted += 1; if(comp_state) { comp_free(&comp_state); } if(count_in_stats) { CStat::instance()->computeStat(CStat::E_ADD_CALL_DURATION, clock_tick - start_time); } call_duration_sum += clock_tick - start_time; call_duration_nb++; if(pollset_index) { pollset_remove(pollset_index); shutdown(call_socket, SHUT_RDWR); close(call_socket); } /* Deletion of the call variable */ for(int i=0; i<SCEN_VARIABLE_SIZE; i++) { if(M_callVariableTable[i] != NULL) { delete M_callVariableTable[i] ; M_callVariableTable[i] = NULL; } } if(id) { free(id); } if(last_recv_msg) { free(last_recv_msg); } if(last_send_msg) { free(last_send_msg); } if(dialog_route_set) { free(dialog_route_set); } call_established= false ;} void call::connect_socket_if_needed(){ if(call_socket) return; if(!multisocket) return; if(transport == T_UDP) { struct sockaddr_in saddr; sipp_socklen_t len = sizeof(saddr); if(toolMode != MODE_CLIENT) return; if((call_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { ERROR_NO("Unable to get an UDP socket"); } saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = INADDR_ANY; saddr.sin_port = 0; if(bind(call_socket, (sockaddr *)(void *)&saddr, sizeof(saddr))) { ERROR_NO("Unable to bind UDP socket"); } getsockname(call_socket, (sockaddr *)(void *)&saddr, &len);#ifdef __hpux call_port = saddr.sin_port;#else call_port = ntohs((short)saddr.sin_port);#endif } else { /* TCP */ if((call_socket= socket(AF_INET, SOCK_STREAM, 0))== -1) { ERROR_NO("Unable to get a TCP socket"); } sipp_customize_socket(call_socket); if(connect(call_socket, (struct sockaddr *)(void *)&remote_sockaddr, sizeof(remote_sockaddr))) { if(errno == EINVAL){ /* This occurs sometime on HPUX but is not a true INVAL */ ERROR("Unable to connect a TCP socket, remote peer error"); } else { ERROR_NO("Unable to connect a TCP socket"); } } } /* Asks to receive incoming messages */ pollset_index = pollset_add(this, call_socket);}bool lost(int percent){ static int inited = 0; if(!lose_packets) return false; if(!percent) return false; if(!inited) { srand((unsigned int) time(NULL)); inited = 1; } if((rand() % 100) < percent) { return true; } else { return false; }}int call::send_raw(char * msg, int index) { void ** state; int sock; int rc; TRACE_MSG((s, "-----------------------------------------------\n" "%s message send:\n\n%s\n", TRANSPORT_TO_STRING(transport), msg)); if(lost(scenario[index] -> lost)) { TRACE_MSG((s, "%s message lost (send).", TRANSPORT_TO_STRING(transport))); if(comp_state) { comp_free(&comp_state); } scenario[index] -> nb_lost++; return 0; } 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 */}int call::sendBuffer(char * msg) { void ** state; int sock; int rc; TRACE_MSG((s, "-----------------------------------------------\n" "%s message send:\n\n%s\n", TRANSPORT_TO_STRING(transport), msg)); 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; if((!last_recv_msg) || (!strlen(last_recv_msg))) { return NULL; } src = last_recv_msg; dest = last_header; while(src = strstr(src, 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 \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 */ while(ptr = strchr(last_header, '\r')) { /* Use strlen(ptr) to include trailing zero */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -