📄 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 * Olivier Jacques * From Hewlett Packard Company. * Shriram Natarajan * Peter Higginson * Eric Miller */#include <iterator>#include <algorithm>#include <fstream>#include <iostream>#include "sipp.hpp"#define KEYWORD_SIZE 64call_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, bool ipv6){ call * new_call; new_call = new call(call_id, ipv6); 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(bool ipv6){ static char call_id[MAX_HEADER_LEN]; call * new_call; if(!next_number) { next_number ++; } sprintf(call_id, "%u-%u@%s", next_number, pid, local_ip); return add_call(call_id, ipv6);}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, bool ipv6) : use_ipv6(ipv6){ memset(this, 0, sizeof(call)); id = strdup(p_id); start_time = clock_tick; call_established=false ; count_in_stats=true ; ack_is_pending=false ; last_recv_msg = NULL; call_remote_socket = 0; // 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); }#ifdef _USE_OPENSSL if(dialog_authentication) { free(dialog_authentication); }#endif call_established= false ;} void call::connect_socket_if_needed(){ if(call_socket) return; if(!multisocket) return; if(transport == T_UDP) { struct sockaddr_storage saddr; sipp_socklen_t len; if(toolMode != MODE_CLIENT) return; if((call_socket = socket(use_ipv6 ? AF_INET6 : AF_INET, SOCK_DGRAM, 0)) == -1) { ERROR_NO("Unable to get an UDP socket"); } memset(&saddr, 0, sizeof(struct sockaddr_storage)); saddr.ss_family = AF_INET; if(bind(call_socket, (sockaddr *)(void *)&saddr, use_ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))) { ERROR_NO("Unable to bind UDP socket"); } if (use_ipv6) { len = sizeof(struct sockaddr_in6); } else { len = sizeof(struct sockaddr_in); } getsockname(call_socket, (sockaddr *)(void *)&saddr, &len); if (use_ipv6) { call_port = ntohs((short)((_RCAST(struct sockaddr_in6 *, &saddr))->sin6_port)); } else { call_port = ntohs((short)((_RCAST(struct sockaddr_in *, &saddr))->sin_port)); } } else { /* TCP */ if((call_socket= socket(use_ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0))== -1) { ERROR_NO("Unable to get a TCP socket"); } sipp_customize_socket(call_socket); /* struct sockaddr_storage *L_dest = &remote_sockaddr; if (use_remote_sending_addr) { L_dest = &remote_sending_sockaddr ; } */ // (struct sockaddr *)(void *)&remote_sockaddr, // (struct sockaddr *)(void *)L_dest, // use_ipv6 ? sizeof(struct sockaddr_in6) : // sizeof(struct sockaddr_in))) { if(connect(call_socket, (struct sockaddr *)(void *)&remote_sockaddr, SOCK_ADDR_SIZE(&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;#ifdef _USE_OPENSSL SSL *ssl; extern SSL *ssl_list[];#endif struct timeval currentTime; GET_TIME (¤tTime); TRACE_MSG((s, "----------------------------------------------- %s\n" "%s message sent:\n\n%s\n", CStat::instance()->formatTime(¤tTime), TRANSPORT_TO_STRING(transport), msg)); if(lost(scenario[index] -> lost)) { TRACE_MSG((s, "%s message voluntary lost (while sending).", 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; if (use_remote_sending_addr) { if (!call_remote_socket) { struct sockaddr_storage *L_dest = &remote_sending_sockaddr; if((call_remote_socket= socket(use_ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0))== -1) { ERROR_NO("Unable to get a TCP socket"); } sipp_customize_socket(call_remote_socket); if(connect(call_remote_socket, (struct sockaddr *)(void *)L_dest, SOCK_ADDR_SIZE(&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"); } } } sock=call_remote_socket ; }#ifdef _USE_OPENSSL ssl = ssl_list[sock];#endif } else { state = &monosocket_comp_state; if(transport == T_UDP) { sock = main_socket; } else { sock = tcp_multiplex;#ifdef _USE_OPENSSL ssl = ssl_tcp_multiplex;#endif } }#ifdef _USE_OPENSSL if ( transport == T_TLS ) { rc = send_message_tls(ssl, state, msg); } else {#endif rc = send_message(sock, state, msg);#ifdef _USE_OPENSSL }#endif 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));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -