mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-07-23 20:51:58 +00:00
891 lines
25 KiB
C
Executable File
891 lines
25 KiB
C
Executable File
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "cpr_types.h"
|
|
#include "cpr_stdio.h"
|
|
#include "cpr_string.h"
|
|
#include "cpr_in.h"
|
|
#include "util_string.h"
|
|
#include "task.h"
|
|
#include "upgrade.h"
|
|
#include "ccsip_task.h"
|
|
#include "config.h"
|
|
#include "ccsip_core.h"
|
|
#include "prot_configmgr.h"
|
|
#include "prot_cfgmgr_private.h"
|
|
#include "sip_common_transport.h"
|
|
#include "phone_debug.h"
|
|
#include "regmgrapi.h"
|
|
#include "rtp_defs.h"
|
|
#include "vcm.h"
|
|
#include "plat_api.h"
|
|
|
|
#define MAX_TOS_VALUE 5
|
|
#define MIN_VOIP_PORT_RANGE 1024
|
|
#define MAX_VOIP_PORT_RANGE 65535
|
|
#define MAX_AUTO_ANSWER_7960 63
|
|
#define MIN_KEEPALIVE_EXPIRES 120
|
|
#define MAX_KEEPALIVE_EXPIRES 7200
|
|
|
|
extern void platform_get_ipv4_address(cpr_ip_addr_t *ip_addr);
|
|
extern void platform_get_ipv6_address(cpr_ip_addr_t *ip_addr);
|
|
extern boolean Is794x;
|
|
|
|
static cpr_ip_addr_t redirected_nat_ipaddr = {0,{0}};
|
|
static void config_set_current_codec_table(int codec_mask,
|
|
rtp_ptype *codec_table);
|
|
|
|
/*********************************************************
|
|
*
|
|
* Network Configuration Settings
|
|
* Look at making these generic and moving them to the
|
|
* network library...
|
|
*
|
|
*********************************************************/
|
|
|
|
static void initCfgTblEntry(int index, const char * name, void *addr, int length,
|
|
parse_func_t parse, print_func_t print,
|
|
const key_table_entry_t *key)
|
|
{
|
|
var_t *table;
|
|
table = &prot_cfg_table[index];
|
|
|
|
table->name = name;
|
|
table->addr = addr;
|
|
table->length = length;
|
|
table->parse_func = parse;
|
|
table->print_func = print;
|
|
table->key_table = key;
|
|
|
|
}
|
|
|
|
/* Function: protCfgTblInit()
|
|
*
|
|
* Description: Initializes line specific params in prot_cfg_table
|
|
*
|
|
* Parameters:
|
|
*
|
|
* Returns:
|
|
*/
|
|
void protCfgTblInit()
|
|
{
|
|
int i;
|
|
memset(&prot_cfg_block, 0, sizeof(prot_cfg_block));
|
|
for (i=0; i< MAX_CONFIG_LINES; i++) {
|
|
initCfgTblEntry(CFGID_LINE_INDEX+i, "Index", CFGVAR(line[i].index), PA_INT, PR_INT, 0);
|
|
initCfgTblEntry(CFGID_LINE_FEATURE+i, "Feat", CFGVAR(line[i].feature), PA_INT, PR_INT, 0);
|
|
initCfgTblEntry(CFGID_LINE_MAXNUMCALLS+i, "MNC", CFGVAR(line[i].maxnumcalls), PA_INT, PR_INT, 0);
|
|
initCfgTblEntry(CFGID_LINE_BUSY_TRIGGER+i, "BT", CFGVAR(line[i].busy_trigger), PA_INT, PR_INT, 0);
|
|
initCfgTblEntry(CFGID_PROXY_ADDRESS+i, "ProxyAddr", CFGVAR(line[i].proxy_address), PA_STR, PR_STR, 0);
|
|
initCfgTblEntry(CFGID_PROXY_PORT+i, "ProxyPort", CFGVAR(line[i].proxy_port), PA_INT, PR_INT, 0);
|
|
initCfgTblEntry(CFGID_LINE_CALL_WAITING+i, "CWait", CFGVAR(line[i].call_waiting), PA_INT, PR_INT, 0);
|
|
initCfgTblEntry(CFGID_LINE_AUTOANSWER_ENABLED+i, "AAns", CFGVAR(line[i].autoanswer), PA_INT, PR_INT, 0);
|
|
initCfgTblEntry(CFGID_LINE_AUTOANSWER_MODE+i, "AAnsMode", CFGVAR(line[i].autoanswer_mode), PA_STR, PR_STR, 0);
|
|
initCfgTblEntry(CFGID_LINE_MSG_WAITING_LAMP+i, "MWILamp", CFGVAR(line[i].msg_waiting_lamp), PA_INT, PR_INT, 0);
|
|
initCfgTblEntry(CFGID_LINE_MESSAGE_WAITING_AMWI+i, "AMWI", CFGVAR(line[i].msg_waiting_amwi), PA_INT, PR_INT, 0);
|
|
initCfgTblEntry(CFGID_LINE_RING_SETTING_IDLE+i, "RingIdle", CFGVAR(line[i].ring_setting_idle), PA_INT, PR_INT, 0);
|
|
initCfgTblEntry(CFGID_LINE_RING_SETTING_ACTIVE+i, "RingActive", CFGVAR(line[i].ring_setting_active), PA_INT, PR_INT, 0);
|
|
initCfgTblEntry(CFGID_LINE_NAME+i, "Name", CFGVAR(line[i].name), PA_STR, PR_STR, 0);
|
|
initCfgTblEntry(CFGID_LINE_AUTHNAME+i, "AuthName", CFGVAR(line[i].authname), PA_STR, PR_STR, 0);
|
|
initCfgTblEntry(CFGID_LINE_PASSWORD+i, "Passwd", CFGVAR(line[i].password), PA_STR, PR_STR, 0);
|
|
initCfgTblEntry(CFGID_LINE_DISPLAYNAME+i, "DisplayName", CFGVAR(line[i].displayname), PA_STR, PR_STR, 0);
|
|
initCfgTblEntry(CFGID_LINE_CONTACT+i, "Contact", CFGVAR(line[i].contact), PA_STR, PR_STR, 0);
|
|
initCfgTblEntry(CFGID_LINE_CFWDALL+i, "CfwdAll", CFGVAR(line[i].cfwdall), PA_STR, PR_STR, 0);
|
|
initCfgTblEntry(CFGID_LINE_SPEEDDIAL_NUMBER+i, "speedDialNumber", CFGVAR(line[i].speeddial_number), PA_STR, PR_STR, 0);
|
|
initCfgTblEntry(CFGID_LINE_RETRIEVAL_PREFIX+i, "retrievalPrefix", CFGVAR(line[i].retrieval_prefix), PA_STR, PR_STR, 0);
|
|
initCfgTblEntry(CFGID_LINE_MESSAGES_NUMBER+i, "messagesNumber", CFGVAR(line[i].messages_number), PA_STR, PR_STR, 0);
|
|
initCfgTblEntry(CFGID_LINE_FWD_CALLER_NAME_DIPLAY+i, "callerName", CFGVAR(line[i].fwd_caller_name_display), PA_INT, PR_INT, 0);
|
|
initCfgTblEntry(CFGID_LINE_FWD_CALLER_NUMBER_DIPLAY+i, "callerName", CFGVAR(line[i].fwd_caller_number_display), PA_INT, PR_INT, 0);
|
|
initCfgTblEntry(CFGID_LINE_FWD_REDIRECTED_NUMBER_DIPLAY+i, "redirectedNumber", CFGVAR(line[i].fwd_redirected_number_display), PA_INT, PR_INT, 0);
|
|
initCfgTblEntry(CFGID_LINE_FWD_DIALED_NUMBER_DIPLAY+i, "dialedNumber", CFGVAR(line[i].fwd_dialed_number_display), PA_INT, PR_INT, 0);
|
|
initCfgTblEntry(CFGID_LINE_FEATURE_OPTION_MASK+i, "featureOptionMask", CFGVAR(line[i].feature_option_mask), PA_INT, PR_INT, 0);
|
|
}
|
|
|
|
initCfgTblEntry(CFGID_PROTOCOL_MAX, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
|
|
/*
|
|
* sip_config_get_net_device_ipaddr()
|
|
*
|
|
* Get the device IP address.
|
|
* Note: the IP Address is returned in the non-Telecaster
|
|
* SIP format, which is not byte reversed.
|
|
* Eg. 0xac2c33f8 = 161.44.51.248
|
|
*/
|
|
void
|
|
sip_config_get_net_device_ipaddr (cpr_ip_addr_t *ip_addr)
|
|
{
|
|
cpr_ip_addr_t ip_addr1 = {0,{0}};
|
|
|
|
platform_get_ipv4_address(&ip_addr1);
|
|
util_ntohl(ip_addr, &ip_addr1);
|
|
}
|
|
|
|
/*
|
|
* sip_config_get_net_device_ipaddr()
|
|
*
|
|
* Get the device IP address.
|
|
* Note: the IP Address is returned in the non-Telecaster
|
|
* SIP format, which is not byte reversed.
|
|
*
|
|
*/
|
|
void
|
|
sip_config_get_net_ipv6_device_ipaddr (cpr_ip_addr_t *ip_addr)
|
|
{
|
|
cpr_ip_addr_t ip_addr1 = {0,{0}};
|
|
|
|
platform_get_ipv6_address(&ip_addr1);
|
|
util_ntohl(ip_addr, &ip_addr1);
|
|
}
|
|
|
|
|
|
/*
|
|
* sip_config_get_nat_ipaddr()
|
|
*
|
|
* Get the nat IP address.
|
|
* Note: the IP Address is returned in the non-Telecaster
|
|
* SIP format, which is not byte reversed.
|
|
* Eg. 0xac2c33f8 = 161.44.51.248
|
|
*/
|
|
void
|
|
sip_config_get_nat_ipaddr (cpr_ip_addr_t *ip_addr)
|
|
{
|
|
cpr_ip_addr_t IPAddress;
|
|
char address[MAX_IPADDR_STR_LEN];
|
|
int dnsErrorCode = 1;
|
|
|
|
if (redirected_nat_ipaddr.type == CPR_IP_ADDR_INVALID) {
|
|
config_get_string(CFGID_NAT_ADDRESS, address, sizeof(address));
|
|
if ((cpr_strcasecmp(address, UNPROVISIONED) != 0) && (address[0] != 0)) {
|
|
dnsErrorCode = dnsGetHostByName(address, &IPAddress, 100, 1);
|
|
}
|
|
|
|
if (dnsErrorCode == 0) {
|
|
util_ntohl(ip_addr, &IPAddress);
|
|
return ;
|
|
} else {
|
|
/*
|
|
* If the NAT address is not provisioned or
|
|
* unavailable, return the local address instead.
|
|
*/
|
|
sip_config_get_net_device_ipaddr(ip_addr);
|
|
return;
|
|
}
|
|
} else {
|
|
*ip_addr = redirected_nat_ipaddr;
|
|
return ;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* sip_config_set_nat_ipaddr()
|
|
*
|
|
* Set the device NAT IP address.
|
|
* Note: the IP Address is returned in the non-Telecaster
|
|
* SIP format, which is not byte reversed.
|
|
* Eg. 0xac2c33f8 = 161.44.51.248
|
|
*/
|
|
void
|
|
sip_config_set_nat_ipaddr (cpr_ip_addr_t *ip_address)
|
|
{
|
|
redirected_nat_ipaddr = *ip_address;
|
|
}
|
|
|
|
/*********************************************************
|
|
*
|
|
* SIP Configuration Settings
|
|
* These should probably be turned into generic config
|
|
* table "gets/sets" or should be moved to a SIP platform
|
|
* file. Maybe ccsip_platform_ui.c since that's where we
|
|
* have the other SIP Platform code. In the long run, we
|
|
* should rename ccsip_platform_ui.c to ccsip_platform.c
|
|
*
|
|
*********************************************************/
|
|
|
|
/*
|
|
* sip_config_get_line_from_button()
|
|
* Some cases CCM sends down line number instead of button number
|
|
* that has to be mapped to correct button number. This function is
|
|
* called to get actual line number for a given button number
|
|
*
|
|
* Returns: actual line number from given button number
|
|
*
|
|
*/
|
|
line_t
|
|
sip_config_get_line_from_button (line_t button)
|
|
{
|
|
line_t max_lines_allowed;
|
|
uint32_t line = 0;
|
|
line_t button_no = 0;
|
|
|
|
if (Is794x) {
|
|
max_lines_allowed = MAX_REG_LINES_794X;
|
|
} else {
|
|
max_lines_allowed = MAX_REG_LINES;
|
|
}
|
|
|
|
if ((button < 1) || (button > max_lines_allowed)) {
|
|
return (button);
|
|
}
|
|
|
|
config_get_line_value(CFGID_LINE_INDEX, &line,
|
|
sizeof(line), button);
|
|
|
|
/* Look for the line number through the configuration
|
|
* <line button="4" lineIndex="3>. If the inddex value is not
|
|
* found then use old way of searching for button. The dolby
|
|
* release of CCM adds index to configuration but older
|
|
* ccm does not support that.
|
|
*/
|
|
|
|
if (line > 0) {
|
|
|
|
return((line_t)line);
|
|
}
|
|
|
|
/* Try old way of calculating the line number
|
|
*/
|
|
|
|
line = 0;
|
|
button_no = 0;
|
|
|
|
for (button_no = 1; button_no <= button; button_no++) {
|
|
|
|
if (sip_config_check_line(button_no) == FALSE) {
|
|
continue;
|
|
}
|
|
|
|
line++;
|
|
}
|
|
|
|
return ((line_t)line);
|
|
}
|
|
|
|
|
|
/*
|
|
* sip_config_get_button_from_line()
|
|
*
|
|
* Some cases CCM sends down line number instead of button number
|
|
* that has to be mapped to correct button number.
|
|
*
|
|
* Parameters: line - the line instance
|
|
*
|
|
* Returns: line - actual button number
|
|
*
|
|
*/
|
|
line_t
|
|
sip_config_get_button_from_line (line_t line)
|
|
{
|
|
line_t max_lines_allowed;
|
|
line_t button = 0;
|
|
uint32_t line_no = 0;
|
|
|
|
if (Is794x) {
|
|
max_lines_allowed = MAX_REG_LINES_794X;
|
|
} else {
|
|
max_lines_allowed = MAX_REG_LINES;
|
|
}
|
|
|
|
if ((line < 1) || (line > max_lines_allowed)) {
|
|
return (line);
|
|
}
|
|
|
|
/* Look for the button number through the configuration
|
|
* <line button="4" lineIndex="3>. If the inddex value is not
|
|
* found then use old way of searching for button. The dolby
|
|
* release of CCM adds index to configuration but older
|
|
* ccm does not support that.
|
|
*/
|
|
|
|
for (button = 1; button <= max_lines_allowed; button++) {
|
|
|
|
config_get_line_value(CFGID_LINE_INDEX, &line_no, sizeof(line_no), button);
|
|
|
|
if ((line_t)line_no == line) {
|
|
return(button);
|
|
}
|
|
}
|
|
|
|
button = 0;
|
|
line_no = 0;
|
|
|
|
/* Nothing has found so far, try old way of calculating the
|
|
* button number
|
|
*/
|
|
do {
|
|
|
|
if (sip_config_check_line(button) == FALSE) {
|
|
button++;
|
|
continue;
|
|
}
|
|
|
|
button++;
|
|
line_no++;
|
|
|
|
} while (((line_t)line_no < line) &&
|
|
button <= max_lines_allowed);
|
|
|
|
|
|
/* Above loop not able to find the correct button number
|
|
* so return value 0
|
|
*/
|
|
if (button > max_lines_allowed) {
|
|
return(0);
|
|
}
|
|
|
|
return (button - 1);
|
|
}
|
|
|
|
|
|
/*
|
|
* sip_config_check_line()
|
|
*
|
|
* Check to see if the indicated line is configured as a DN line
|
|
*
|
|
* Parameters: line - the line instance
|
|
*
|
|
* Returns: TRUE if the indicated line is Valid
|
|
* FALSE if the indicated line is Invalid
|
|
*
|
|
*/
|
|
boolean
|
|
sip_config_check_line (line_t line)
|
|
{
|
|
const char fname[] = "sip_config_check_line";
|
|
char temp[MAX_LINE_NAME_SIZE];
|
|
uint32_t line_feature;
|
|
line_t max_lines_allowed;
|
|
|
|
if (Is794x) {
|
|
max_lines_allowed = MAX_REG_LINES_794X;
|
|
} else {
|
|
max_lines_allowed = MAX_REG_LINES;
|
|
}
|
|
|
|
if ((line < 1) || (line > max_lines_allowed)) {
|
|
if (line != 0) {
|
|
PLAT_ERROR(PLAT_COMMON_F_PREFIX"Invalid Line: %d\n", fname, line);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
config_get_line_string(CFGID_LINE_NAME, temp, line, sizeof(temp));
|
|
if (temp[0] == '\0') {
|
|
return FALSE;
|
|
}
|
|
|
|
config_get_line_value(CFGID_LINE_FEATURE, &line_feature,
|
|
sizeof(line_feature), line);
|
|
|
|
if (line_feature != cfgLineFeatureDN) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
/*
|
|
* sip_config_local_line_get()
|
|
*
|
|
* Get the Line setting.
|
|
* Note: The UI has serious problems if there are gaps in the
|
|
* line names. Therefore, lines must be sequential. In
|
|
* other words, if lines 1, 2, and 4 have names, this routine
|
|
* will return that two lines are active. Once Line three is
|
|
* found to be unprovisioned, line 4 will be ignored.
|
|
*/
|
|
line_t
|
|
sip_config_local_line_get (void)
|
|
{
|
|
if (Is794x) {
|
|
return (MAX_REG_LINES_794X);
|
|
}
|
|
return (MAX_REG_LINES);
|
|
}
|
|
/*
|
|
* sip_config_get_keepalive_expires()
|
|
*
|
|
* Returns the keepalive expires configured.
|
|
* The minimum allowed value is returned if
|
|
* configured value is less than the minimum
|
|
* allowed value.If the configured value is
|
|
* greater than the maximum allowed then the
|
|
* maximum allowed value is returned.
|
|
*
|
|
*/
|
|
int
|
|
sip_config_get_keepalive_expires()
|
|
{
|
|
int keepalive_interval = 0;
|
|
|
|
config_get_value(CFGID_TIMER_KEEPALIVE_EXPIRES, &keepalive_interval,
|
|
sizeof(keepalive_interval));
|
|
|
|
if (keepalive_interval < MIN_KEEPALIVE_EXPIRES) {
|
|
keepalive_interval = MIN_KEEPALIVE_EXPIRES;
|
|
TNP_DEBUG(DEB_F_PREFIX"Keepalive interval less than minimum acceptable.Resetting it to %d\n",
|
|
DEB_F_PREFIX_ARGS(SIP_KA, "sip_config_get_keepalive_expires"),
|
|
keepalive_interval);
|
|
} else if (keepalive_interval > MAX_KEEPALIVE_EXPIRES) {
|
|
keepalive_interval = MAX_KEEPALIVE_EXPIRES;
|
|
TNP_DEBUG(DEB_F_PREFIX"Keepalive interval more than maximum acceptable.Resetting it to %d\n",
|
|
DEB_F_PREFIX_ARGS(SIP_KA, "sip_config_get_keepalive_expires"),
|
|
keepalive_interval);
|
|
}
|
|
|
|
return keepalive_interval;
|
|
}
|
|
/*
|
|
* sip_config_get_display_name()
|
|
*
|
|
* Get the display name
|
|
*/
|
|
void
|
|
sip_config_get_display_name (line_t line, char *buffer, int buffer_len)
|
|
{
|
|
|
|
config_get_line_string(CFGID_LINE_DISPLAYNAME, buffer, line, buffer_len);
|
|
|
|
if ((strcmp(buffer, UNPROVISIONED) == 0) || (buffer[0] == '\0')) {
|
|
config_get_line_string(CFGID_LINE_NAME, buffer, line, buffer_len);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the configured value of preferred codec. The codec may
|
|
* or may not be available by the platform.
|
|
*
|
|
* @param[in] none.
|
|
*
|
|
* @return rtp_ptype of the codec.
|
|
*/
|
|
rtp_ptype
|
|
sip_config_preferred_codec (void)
|
|
{
|
|
key_table_entry_t cfg_preferred_codec;
|
|
|
|
config_get_value(CFGID_PREFERRED_CODEC, &cfg_preferred_codec,
|
|
sizeof(cfg_preferred_codec));
|
|
if ((cfg_preferred_codec.name != NULL) &&
|
|
(cfg_preferred_codec.name[0] != '\0')) {
|
|
/* The configuration has preferred codec configured */
|
|
return (cfg_preferred_codec.value);
|
|
}
|
|
/* No preferred codec configured */
|
|
return (RTP_NONE);
|
|
}
|
|
|
|
/**
|
|
* sip_config_local_supported_codecs_get()
|
|
* Get the locally supported codec list. The returned list
|
|
* of codecs will be in the ordered of preference. If there is
|
|
* preferred condec configured and it is available, the
|
|
* preferred codec will be put on the first entry of the
|
|
* returned list.
|
|
*
|
|
* @param[in,out] aSupportedCodecs - pointer to arrary fo the
|
|
* rtp_ptype to store the result of
|
|
* currenlty available codecs.
|
|
* @param[in] supportedCodecsLen - indicates the number of entry
|
|
* of the aSupportedCodecs.
|
|
*
|
|
* @return number of current codecs available.
|
|
*
|
|
* @pre (aSupportedCodecs != NULL)
|
|
* @pre (supportedCodecsLen != 0)
|
|
*/
|
|
uint16_t
|
|
sip_config_local_supported_codecs_get (rtp_ptype aSupportedCodecs[],
|
|
uint16_t supportedCodecsLen)
|
|
{
|
|
rtp_ptype current_codec_table[MAX_CODEC_ENTRIES+1];
|
|
rtp_ptype *codec;
|
|
rtp_ptype pref_codec;
|
|
uint16_t count = 0;
|
|
int codec_mask;
|
|
boolean preferred_codec_available = FALSE;
|
|
|
|
codec_mask = vcmGetAudioCodecList(VCM_DSP_FULLDUPLEX);
|
|
|
|
if (!codec_mask) {
|
|
codec_mask = VCM_CODEC_RESOURCE_G711 | VCM_CODEC_RESOURCE_OPUS;
|
|
}
|
|
|
|
/*
|
|
* convert the current available codec into the enumerated
|
|
* preferred list.
|
|
*/
|
|
current_codec_table[0] = RTP_NONE;
|
|
current_codec_table[MAX_CODEC_ENTRIES] = RTP_NONE;
|
|
config_set_current_codec_table(codec_mask, ¤t_codec_table[0]);
|
|
|
|
/*
|
|
* Get the configured preferred codec. If one is configured,
|
|
* check it to see if currently it can be supported by the
|
|
* platform. If it is configured and is availble to support,
|
|
* put the preferred codec in the first one of the list.
|
|
*/
|
|
pref_codec = sip_config_preferred_codec();
|
|
if (pref_codec != RTP_NONE) {
|
|
/*
|
|
* There is a configured preferred codec, check to see if
|
|
* the codec is currently avaible or not.
|
|
*/
|
|
codec = ¤t_codec_table[0];
|
|
while (*codec != RTP_NONE) {
|
|
if (pref_codec == *codec) {
|
|
preferred_codec_available = TRUE;
|
|
break;
|
|
}
|
|
codec++;
|
|
}
|
|
}
|
|
|
|
if (preferred_codec_available) {
|
|
/*
|
|
* The preferred codec is configured and the platform
|
|
* currently can support the preferred codec, put it in
|
|
* the first entry.
|
|
*/
|
|
aSupportedCodecs[count] = pref_codec;
|
|
count++;
|
|
} else {
|
|
/*
|
|
* Must init or comparison will be made to uninitialized memory.
|
|
* Do not increment count here since we are not adding RTP_NONE
|
|
* as a supported codec. We are only initializing memory to a
|
|
* known value.
|
|
*/
|
|
aSupportedCodecs[count] = RTP_NONE;
|
|
}
|
|
|
|
codec = ¤t_codec_table[0];
|
|
while (*codec != RTP_NONE) {
|
|
if (count < supportedCodecsLen) {
|
|
if (*codec != aSupportedCodecs[0]) {
|
|
aSupportedCodecs[count] = *codec;
|
|
count++;
|
|
}
|
|
}
|
|
codec++;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
/*
|
|
* sip_config_local_supported_codecs_get()
|
|
*
|
|
* Get the locally supported codec list.
|
|
*/
|
|
uint16_t
|
|
sip_config_video_supported_codecs_get (rtp_ptype aSupportedCodecs[],
|
|
uint16_t supportedCodecsLen, boolean isOffer)
|
|
{
|
|
uint16_t count = 0;
|
|
int codec_mask;
|
|
cc_uint32_t major_ver, minor_ver;
|
|
|
|
if ( isOffer ) {
|
|
codec_mask = vcmGetVideoCodecList(VCM_DSP_FULLDUPLEX);
|
|
} else {
|
|
/* we are trying to match the answer then we
|
|
already have the rx stream open */
|
|
//codec_mask = vcmGetVideoCodecList(DSP_ENCODEONLY);
|
|
codec_mask = vcmGetVideoCodecList(VCM_DSP_IGNORE);
|
|
}
|
|
if ( codec_mask & VCM_CODEC_RESOURCE_VP8) {
|
|
aSupportedCodecs[count] = RTP_VP8;
|
|
count++;
|
|
}
|
|
if ( codec_mask & VCM_CODEC_RESOURCE_H264) {
|
|
/*
|
|
* include payload type for packetization mode 1 only if ucm sis version
|
|
* is equal to or greater than 5.1.0 (AngelFire).
|
|
*/
|
|
platGetSISProtocolVer(&major_ver, &minor_ver, NULL, NULL);
|
|
if ((major_ver > SIS_PROTOCOL_MAJOR_VERSION_ANGELFIRE) ||
|
|
(major_ver == SIS_PROTOCOL_MAJOR_VERSION_ANGELFIRE &&
|
|
minor_ver >= SIS_PROTOCOL_MINOR_VERSION_ANGELFIRE)) {
|
|
if (vcmGetVideoMaxSupportedPacketizationMode() == 1) {
|
|
aSupportedCodecs[count] = RTP_H264_P1;
|
|
count++;
|
|
}
|
|
}
|
|
aSupportedCodecs[count] = RTP_H264_P0;
|
|
count++;
|
|
}
|
|
if ( codec_mask & VCM_CODEC_RESOURCE_H263) {
|
|
aSupportedCodecs[count] = RTP_H263;
|
|
count++;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
/**
|
|
* The function fills in the given codec array based on the
|
|
* platform bit mask of codecs. Note, that the enumerated list
|
|
* produced is also in the preferred order.
|
|
*
|
|
* @param[in] codec_mask - platform bit mask corresponding to the
|
|
* codecs.
|
|
* @param[in/out] codecs - pointer to array of for storing the
|
|
* output of the enumerated codec based on
|
|
* bit set in the codec_mask.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @pre (codec_table != NULL)
|
|
* @pre storge of codec_table must be last enough to holds
|
|
* supported codec in the bit mask.
|
|
*/
|
|
static void
|
|
config_set_current_codec_table (int codec_mask, rtp_ptype *codecs)
|
|
{
|
|
int idx = 0;
|
|
|
|
if (codec_mask & VCM_CODEC_RESOURCE_OPUS) {
|
|
codecs[idx] = RTP_OPUS;
|
|
idx++;
|
|
}
|
|
|
|
if (codec_mask & VCM_CODEC_RESOURCE_G711) {
|
|
codecs[idx] = RTP_PCMU;
|
|
idx++;
|
|
codecs[idx] = RTP_PCMA;
|
|
idx++;
|
|
}
|
|
|
|
if (codec_mask & VCM_CODEC_RESOURCE_G729A) {
|
|
codecs[idx] = RTP_G729;
|
|
idx++;
|
|
}
|
|
|
|
if (codec_mask & VCM_CODEC_RESOURCE_LINEAR) {
|
|
codecs[idx] = RTP_L16;
|
|
idx++;
|
|
}
|
|
|
|
if (codec_mask & VCM_CODEC_RESOURCE_G722) {
|
|
codecs[idx] = RTP_G722;
|
|
idx++;
|
|
}
|
|
|
|
if (codec_mask & VCM_CODEC_RESOURCE_iLBC) {
|
|
codecs[idx] = RTP_ILBC;
|
|
idx++;
|
|
}
|
|
|
|
if (codec_mask & VCM_CODEC_RESOURCE_iSAC) {
|
|
codecs[idx] = RTP_ISAC;
|
|
idx++;
|
|
}
|
|
|
|
codecs[idx] = RTP_NONE;
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* sip_config_local_dtmf_dblevels_get()
|
|
*
|
|
* Get the DTMF DB levels
|
|
*/
|
|
uint32_t
|
|
sip_config_local_dtmf_dblevels_get (void)
|
|
{
|
|
int value;
|
|
|
|
config_get_value(CFGID_DTMF_DB_LEVEL, &value, sizeof(value));
|
|
switch (value) {
|
|
case 0:
|
|
return 0; // Mute
|
|
case 1:
|
|
return 2900; // 6 dB down
|
|
case 2:
|
|
return 4096; // 3 dB down
|
|
case 3:
|
|
return 5786; // Nominal amplitude
|
|
// (-8.83 dBm0 to network, -11.83 dBm0 local)
|
|
case 4:
|
|
return 8173; // 3 dB up
|
|
case 5:
|
|
return 11544; // 6 dB up
|
|
default:
|
|
return 5786; // Nominal amplitude
|
|
}
|
|
}
|
|
|
|
/*
|
|
* sip_config_get_line_by_called_number
|
|
*
|
|
* Return the line by the given called_number
|
|
*/
|
|
line_t sip_config_get_line_by_called_number (line_t start_line, const char *called_number)
|
|
{
|
|
int i;
|
|
line_t max_lines;
|
|
line_t line = 0;
|
|
char line_name[MAX_LINE_NAME_SIZE];
|
|
char contact[MAX_LINE_CONTACT_SIZE];
|
|
char *name;
|
|
|
|
max_lines = sip_config_local_line_get();
|
|
|
|
/*
|
|
* Check the called number for the E.164 "+"
|
|
* and ignore it if present.
|
|
*/
|
|
if (called_number[0] == '+') {
|
|
called_number++;
|
|
}
|
|
|
|
for (i = start_line; i <= max_lines; i++) {
|
|
if (sip_config_check_line((line_t)i)) {
|
|
config_get_line_string(CFGID_LINE_NAME, line_name, i,
|
|
sizeof(line_name));
|
|
/*
|
|
* Check the configured line name for the E.164 "+"
|
|
* and ignore it if present.
|
|
*/
|
|
name = &line_name[0];
|
|
if (line_name[0] == '+') {
|
|
name++;
|
|
}
|
|
|
|
if (cpr_strcasecmp(called_number, name) == 0) {
|
|
line = (line_t)i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If line not found - check with contact list
|
|
if (line == 0) {
|
|
for (i = start_line; i <= max_lines; i++) {
|
|
if (sip_config_check_line((line_t)i)) {
|
|
config_get_line_string(CFGID_LINE_CONTACT, contact, i,
|
|
sizeof(contact));
|
|
if (cpr_strcasecmp(called_number, contact) == 0) {
|
|
line = (line_t)i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (line);
|
|
}
|
|
|
|
/*********************************************************
|
|
*
|
|
* SIP Config API
|
|
* The routines below with the "prot" prefix are called
|
|
* by the config system. The calls that start with "sip"
|
|
* are helper functions for the SIP implementation of the
|
|
* "prot" API.
|
|
*
|
|
*********************************************************/
|
|
|
|
/*
|
|
* sip_minimum_config_check()
|
|
*
|
|
* Return indication if the SIP minimum configuration
|
|
* requirements have been met.
|
|
* Returns 0 if minimum config is met
|
|
* Returns non-zero if minimum config has not been met
|
|
* (eg. missing at least 1 required parameter)
|
|
*/
|
|
int
|
|
sip_minimum_config_check (void)
|
|
{
|
|
char str_val[MAX_IPADDR_STR_LEN];
|
|
char line_name[MAX_LINE_NAME_SIZE];
|
|
int value;
|
|
|
|
/*
|
|
* Make sure that line 1 is configured
|
|
*/
|
|
config_get_line_string(CFGID_LINE_NAME, line_name, 1, sizeof(line_name));
|
|
if ((strcmp(line_name, UNPROVISIONED) == 0) || (line_name[0] == '\0')) {
|
|
return -1;
|
|
}
|
|
|
|
config_get_line_string(CFGID_PROXY_ADDRESS, str_val, 1, MAX_IPADDR_STR_LEN);
|
|
if ((strcmp(str_val, UNPROVISIONED) == 0) || (str_val[0] == '\0')) {
|
|
return -1;
|
|
}
|
|
|
|
config_get_line_value(CFGID_PROXY_PORT, &value, sizeof(value), 1);
|
|
if (value == 0) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* prot_config_change_notify()
|
|
* Let the SIP stack know that a config change has occurred.
|
|
*
|
|
*/
|
|
int
|
|
prot_config_change_notify (int notify_type)
|
|
{
|
|
if (SIPTaskProcessConfigChangeNotify(notify_type) < 0) {
|
|
//CPR TODO: need reference for
|
|
CCSIP_DEBUG_ERROR(PLAT_COMMON_F_PREFIX"SIPTaskProcessConfigChangeNotify() "
|
|
"returned error.\n", "prot_config_change_notify");
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
/*
|
|
* prot_config_check_line_name()
|
|
* Makes sure that there are no spaces in the SIP Line Names
|
|
*
|
|
* Returns: TRUE if the Name is Valid
|
|
* FALSE if the Name is Invalid
|
|
*
|
|
*/
|
|
boolean
|
|
prot_config_check_line_name (char *line_name)
|
|
{
|
|
while ((*line_name != ' ') && (*line_name != NUL)) {
|
|
line_name++;
|
|
}
|
|
|
|
if (*line_name == ' ') {
|
|
return (FALSE);
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
/*
|
|
* prot_sanity_check_config_settings()
|
|
*
|
|
, Louis* Checks the sanity of the protocol config block values
|
|
* and sets them to defaults if they are incorrect.
|
|
*/
|
|
int
|
|
prot_sanity_check_config_settings (void)
|
|
{
|
|
int retval = 0;
|
|
return retval;
|
|
}
|
|
|
|
|
|
/*
|
|
* prot_shutdown()
|
|
*
|
|
* Shut down the protocol stack.
|
|
*/
|
|
|
|
void
|
|
prot_shutdown (void)
|
|
{
|
|
sip_shutdown();
|
|
}
|