📄 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 * Venkatesh * Enrico Hartung * Nasir Khan * Lee Ballard * Guillaume Teissier from FTR&D * Wolfgang Beck * Venkatesh */#include <iterator>#include <algorithm>#include <fstream>#include <iostream>#ifdef PCAPPLAY#include <assert.h>#include "send_packets.h"#endif#include "sipp.hpp"#define KEYWORD_SIZE 64#ifdef _USE_OPENSSLextern SSL *ssl_list[];extern struct pollfd pollfiles[];extern SSL_CTX *sip_trp_ssl_ctx;#endifextern map<string, int> map_perip_fd;call_map calls;#ifdef PCAPPLAY/* send_packets pthread wrapper */void *send_wrapper(void *);#endif/************** 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;}#ifdef _USE_OPENSSLcall * add_call(char * call_id , int P_pollset_indx, 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; new_call -> pollset_index = P_pollset_indx; /* 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;}#endifcall * add_call(bool ipv6){ static char call_id[MAX_HEADER_LEN]; call * new_call; char * src = call_id_string; int count = 0; if(!next_number) { next_number ++; } while (*src && count < MAX_HEADER_LEN-1) { if (*src == '%') { ++src; switch(*src++) { case 'u': count += snprintf(&call_id[count], MAX_HEADER_LEN-count-1,"%u", next_number); break; case 'p': count += snprintf(&call_id[count], MAX_HEADER_LEN-count-1,"%u", pid); break; case 's': count += snprintf(&call_id[count], MAX_HEADER_LEN-count-1,"%s", local_ip); break; default: // treat all unknown sequences as %% call_id[count++] = '%'; break; } } else { call_id[count++] = *src++; } } call_id[count] = 0; return add_call(call_id, ipv6);}call * get_call(char * call_id){ call * call_ptr; call_map::iterator call_it ; call_it = calls.find(call_map::key_type(call_id)); call_ptr = (call_it != calls.end()) ? call_it->second : NULL ; return call_ptr;}void delete_call(char * call_id){ call * call_ptr; call_map::iterator call_it ; call_it = calls.find(call_map::key_type(call_id)); call_ptr = (call_it != calls.end()) ? call_it->second : NULL ; if(call_ptr) { calls.erase(call_it); delete call_ptr; open_calls--; } else { if (start_calls == 0) { ERROR("Call not found"); } } }#ifdef PCAPPLAY/******* Media information management *************************//* * Look for "c=IN IP4 " pattern in the message and extract the following value * which should be IP address */uint32_t get_remote_ip_media(char *msg){ char pattern[] = "c=IN IP4 "; char *begin, *end; char ip[32]; begin = strstr(msg, pattern); if (!begin) { fprintf(stderr, "%s", msg); ERROR("No media IP found"); } begin += sizeof("c=IN IP4 ") - 1; end = strstr(begin, "\r\n"); if (!end) ERROR("No CRLF found"); memset(ip, 0, 32); strncpy(ip, begin, end - begin); return inet_addr(ip);}/* * Look for "c=IN IP6 " pattern in the message and extract the following value * which should be IPv6 address */struct in6_addr get_remote_ipv6_media(char *msg){ char pattern[] = "c=IN IP6 "; char *begin, *end; char ip[128]; in6_addr ipv6; begin = strstr(msg, pattern); if (!begin) { fprintf(stderr, "%s", msg); ERROR("No media IPv6 found"); } begin += sizeof("c=IN IP6 ") - 1; end = strstr(begin, "\r\n"); if (!end) ERROR("No CRLF found"); memset(ip, 0, 128); strncpy(ip, begin, end - begin); memset(&ipv6, 0, sizeof(ipv6)); if (!inet_pton(AF_INET6, ip, &ipv6)) { ERROR("No media IPv6 found"); } return ipv6;}/* * Look for "m=audio " pattern in the message and extract the following value * which should be port number */uint16_t get_remote_audio_port_media(char *msg){ char pattern[] = "m=audio "; char *begin, *end; char number[5]; begin = strstr(msg, pattern); if (!begin) ERROR("No audio media port found in SDP"); begin += sizeof("m=audio ") - 1; end = strstr(begin, "\r\n"); if (!end) ERROR("get_remote_audio_port_media: no CRLF found"); memset(number, 0, 5); strncpy(number, begin, end - begin); return atoi(number);}/* * Look for "m=video " pattern in the message and extract the following value * which should be port number */uint16_t get_remote_video_port_media(char *msg){ char pattern[] = "m=video "; char *begin, *end; char number[5]; begin = strstr(msg, pattern); if (!begin) { /* m=video not found */ return 0; } begin += sizeof("m=video ") - 1; end = strstr(begin, "\r\n"); if (!end) ERROR("get_remote_video_port_media: no CRLF found"); memset(number, 0, 5); strncpy(number, begin, end - begin); return atoi(number);}/* * IPv{4,6} compliant */void call::get_remote_media_addr(char *msg) { uint16_t video_port; if (media_ip_is_ipv6) { struct in6_addr ip_media; ip_media = get_remote_ipv6_media(msg); (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_flowinfo = 0; (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_scope_id = 0; (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_family = AF_INET6; (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_port = get_remote_audio_port_media(msg); (_RCAST(struct sockaddr_in6 *, &(play_args_a.to)))->sin6_addr = ip_media; video_port = get_remote_video_port_media(msg); if (video_port) { /* We have video in the SDP: set the to_video addr */ (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_flowinfo = 0; (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_scope_id = 0; (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_family = AF_INET6; (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_port = video_port; (_RCAST(struct sockaddr_in6 *, &(play_args_v.to)))->sin6_addr = ip_media; } } else { uint32_t ip_media; ip_media = get_remote_ip_media(msg); (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_family = AF_INET; (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_port = get_remote_audio_port_media(msg); (_RCAST(struct sockaddr_in *, &(play_args_a.to)))->sin_addr.s_addr = ip_media; video_port = get_remote_video_port_media(msg); if (video_port) { /* We have video in the SDP: set the to_video addr */ (_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_family = AF_INET; (_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_port = video_port; (_RCAST(struct sockaddr_in *, &(play_args_v.to)))->sin_addr.s_addr = ip_media; } } hasMediaInformation = 1;}#endif/******* 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; cseq = base_cseq; nb_last_delay = 0; #ifdef _USE_OPENSSL m_ctx_ssl = NULL ; m_bio = NULL ;#endif pollset_index = 0 ; poll_flag_write = false ; call_remote_socket = 0; // initialising the CallVariable with the Scenario variable bool test_var=false; int i,j; for(i=0; i<SCEN_VARIABLE_SIZE; i++) { for (j=0; j<SCEN_MAX_MESSAGES; j++) { if(scenVariableTable[i][j] != NULL) { test_var=true; break; } } if (test_var) { 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; } }#ifdef PCAPPLAY memset(&(play_args_a.to), 0, sizeof(struct sockaddr_storage)); memset(&(play_args_v.to), 0, sizeof(struct sockaddr_storage)); memset(&(play_args_a.from), 0, sizeof(struct sockaddr_storage)); memset(&(play_args_v.from), 0, sizeof(struct sockaddr_storage)); hasMediaInformation = 0; media_thread = 0;#endif peer_tag[0] = '\0';}call::~call(){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -