📄 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 * Vlad Troyanker * Charles P Wright from IBM Research * Amit On from Followap */#include <iterator>#include <algorithm>#include <fstream>#include <iostream>#include <sys/types.h>#include <sys/wait.h>#ifdef PCAPPLAY#include "send_packets.h"#endif#include "sipp.hpp"#include "assert.h"#define KEYWORD_SIZE 256#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;call_list running_calls;timewheel paused_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;unsigned int get_tdm_map_number(unsigned int number) { unsigned int nb = 0; unsigned int i=0; unsigned int interval=0; unsigned int random=0; bool found = false; /* Find a number in the tdm_map which is not in use */ interval = (tdm_map_a+1) * (tdm_map_b+1) * (tdm_map_c+1); random = rand() % interval; while ((i<interval) && (!found)) { if (tdm_map[(random + i - 1) % interval] == false) { nb = (random + i - 1) % interval; found = true; } i++; } if (!found) { return 0; } else { return nb+1; } }call * add_call(char * call_id, bool ipv6){ call * new_call; unsigned int nb; if(!next_number) { next_number ++; } if (use_tdmmap) { nb = get_tdm_map_number(next_number); if (nb != 0) { /* Mark the entry in the list as busy */ tdm_map[nb - 1] = true; } else { /* Can't create the new call */ WARNING("Can't create new outgoing call: all tdm_map circuits busy"); return NULL; } } new_call = new call(call_id, ipv6); if(!new_call) { ERROR("Memory Overflow"); } /* All calls must exist in the map. */ calls[std::string(call_id)] = new_call; /* All calls start off in the running state. */ add_running_call(new_call); new_call -> number = next_number; new_call -> tdm_map_number = nb - 1; /* 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 = add_call(call_id, ipv6); new_call -> pollset_index = P_pollset_indx; 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) { if (use_tdmmap) tdm_map[call_ptr->tdm_map_number] = false; calls.erase(call_it); if (call_ptr->running) { remove_running_call(call_ptr); } else { paused_calls.remove_paused_call(call_ptr); } delete call_ptr; open_calls--; } else { if (start_calls == 0) { ERROR("Call not found"); } }}void delete_calls(void){ call * call_ptr; call_map::iterator call_it ; call_it = calls.begin(); while (call_it != calls.end()) { call_ptr = (call_it != calls.end()) ? call_it->second : NULL ; WARNING_P1("Aborting call with Call-Id '%s'", call_ptr->id); call_ptr->abortCall(); call_it = calls.begin(); }}/* Routines for running calls. *//* Get the overall list of running calls. */call_list * get_running_calls(){ return & running_calls;}/* Put this call in the run queue. */void add_running_call(call *call) { call->runit = running_calls.insert(running_calls.end(), call); call->running = true;}/* Remove this call from the run queue. */bool remove_running_call(call *call) { if (!call->running) { return false; } running_calls.erase(call->runit); call->running = false; return true;}/* When should this call wake up? */unsigned int call_wake(call *call) { unsigned int wake = 0; if (call->paused_until) { wake = call->paused_until; } if (call->next_retrans && (!wake || (call->next_retrans < wake))) { wake = call->next_retrans; } if (call->recv_timeout && (!wake || (call->recv_timeout < wake))) { wake = call->recv_timeout; } return wake;}call_list *timewheel::call2list(call *call) { unsigned int wake = call_wake(call); unsigned int wake_sigbits = wake; unsigned int base_sigbits = wheel_base; if (wake == 0) { return &forever_list; } wake_sigbits /= LEVEL_ONE_SLOTS; base_sigbits /= LEVEL_ONE_SLOTS; if (wake_sigbits == base_sigbits) { return &wheel_one[wake % LEVEL_ONE_SLOTS]; } wake_sigbits /= LEVEL_TWO_SLOTS; base_sigbits /= LEVEL_TWO_SLOTS; if (wake_sigbits == base_sigbits) { return &wheel_two[(wake / LEVEL_ONE_SLOTS) % LEVEL_TWO_SLOTS]; } assert(wake_sigbits < LEVEL_THREE_SLOTS); return &wheel_three[wake_sigbits];}int expire_paused_calls() { return paused_calls.expire_paused_calls();}int paused_calls_count() { return paused_calls.size();}void remove_paused_call(call *call) { assert(!call->running); paused_calls.remove_paused_call(call);}/* Iterate through our sorted set of paused calls, removing those that * should no longer be paused, and adding them to the run queue. */int timewheel::expire_paused_calls() { int found = 0; while (wheel_base < clock_tick) { int slot1 = wheel_base % LEVEL_ONE_SLOTS; /* Migrate calls from slot2 when we hit 0. */ if (slot1 == 0) { int slot2 = (wheel_base / LEVEL_ONE_SLOTS) % LEVEL_TWO_SLOTS; /* If slot2 is also zero, we must migrate calls from slot3 into slot2. */ if (slot2 == 0) { int slot3 = ((wheel_base / LEVEL_ONE_SLOTS) / LEVEL_TWO_SLOTS); assert(slot3 < LEVEL_THREE_SLOTS); for (call_list::iterator l3it = wheel_three[slot3].begin(); l3it != wheel_three[slot3].end(); l3it++) { /* Migrate this call to wheel two. */ add_paused_call(*l3it, false); } wheel_three[slot3].clear(); } for (call_list::iterator l2it = wheel_two[slot2].begin(); l2it != wheel_two[slot2].end(); l2it++) { /* Migrate this call to wheel one. */ add_paused_call(*l2it, false); } wheel_two[slot2].clear(); } found += wheel_one[slot1].size(); for(call_list::iterator it = wheel_one[slot1].begin(); it != wheel_one[slot1].end(); it++) { add_running_call(*it); count--; } wheel_one[slot1].clear(); wheel_base++; } return found;}void timewheel::add_paused_call(call *call, bool increment) { call_list *list = call2list(call); call->pauseit = list->insert(list->end(), call); if (increment) { count++; }}void timewheel::remove_paused_call(call *call) { call_list *list = call2list(call); list->erase(call->pauseit); count--;}timewheel::timewheel() { count = 0; wheel_base = clock_tick;}int timewheel::size() { return count;}#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) { /* Can't find what we're looking at -> return no address */ return INADDR_NONE; } begin += sizeof("c=IN IP4 ") - 1; end = strstr(begin, "\r\n"); if (!end) return INADDR_NONE; 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 */uint8_t get_remote_ipv6_media(char *msg, struct in6_addr addr){ char pattern[] = "c=IN IP6 "; char *begin, *end; char ip[128]; memset(&addr, 0, sizeof(addr)); memset(ip, 0, 128);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -