2242 lines
85 KiB
C
Executable File
2242 lines
85 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 <limits.h>
|
|
|
|
#include "CCProvider.h"
|
|
#include "ccSession.h"
|
|
#include "ccsip_task.h"
|
|
#include "cpr.h"
|
|
#include "cpr_stdlib.h"
|
|
#include "cpr_ipc.h"
|
|
#include "phone.h"
|
|
#include "phntask.h"
|
|
#include "ccapi.h"
|
|
#include "debug.h"
|
|
#include "phone_debug.h"
|
|
#include "dialplanint.h"
|
|
#include "configmgr.h"
|
|
#include "prot_configmgr.h"
|
|
#include "lsm.h"
|
|
#include "sip_common_regmgr.h"
|
|
#include "sessionHash.h"
|
|
#include "pres_sub_not_handler.h"
|
|
#include "cc_call_listener.h"
|
|
#include "cc_service_listener.h"
|
|
#include "cc_config.h"
|
|
#include "cc_device_listener.h"
|
|
#include "cc_service_listener.h"
|
|
#include "plat_api.h"
|
|
#include "cc_info_listener.h"
|
|
#include "cc_blf_listener.h"
|
|
#include "platform_api.h"
|
|
#include "ccapp_task.h"
|
|
#include "ccapi.h"
|
|
#include "capability_set.h"
|
|
#include "plat_debug.h"
|
|
|
|
#include "config_api.h"
|
|
#include "ccapi_call_info.h"
|
|
#include "ccapi_call_listener.h"
|
|
#include "ccapi_snapshot.h"
|
|
#include "ccapi_device.h"
|
|
#include "ccapi_line_listener.h"
|
|
#include "ccapi_device_listener.h"
|
|
#include "cc_device_manager.h"
|
|
#include "call_logger.h"
|
|
#include "subscription_handler.h"
|
|
#include "ccapi_device_info.h"
|
|
#include "conf_roster.h"
|
|
#include "reset_api.h"
|
|
//#include "prlog.h"
|
|
|
|
/*---------------------------------------------------------
|
|
*
|
|
* Definitions
|
|
*
|
|
*/
|
|
#define NOTIFY_CALL_STATUS (data->state == OFFHOOK? "OFFHOOK" : \
|
|
data->state == ONHOOK? "ONHOOK" : \
|
|
data->state == RINGOUT? "RINGOUT" : \
|
|
data->state == RINGIN? "RINGIN" : \
|
|
data->state == PROCEED ? "PROCEED" : \
|
|
data->state == CONNECTED ? "CONNECTED" : \
|
|
data->state == HOLD ? "HOLD" : \
|
|
data->state == REMHOLD ? "REMHOLD" : \
|
|
data->state == RESUME ? "RESUME" : \
|
|
data->state == BUSY ? "BUSY" : \
|
|
data->state == REORDER ? "REORDER" : \
|
|
data->state == CONFERENCE ? "CONFERENCE" : \
|
|
data->state == DIALING ? "DIALING" : \
|
|
data->state == REMINUSE ? "REMINUSE" : \
|
|
data->state == HOLDREVERT ? "HOLDREVERT" :\
|
|
data->state == WHISPER ? "WHISPER" : \
|
|
data->state == PRESERVATION ? "PRESERVATION" : \
|
|
data->state == WAITINGFORDIGITS ? "WAITINGFORDIGITS" : \
|
|
"Unknown state")
|
|
|
|
#define CCAPP_TASK_CMD_PRINT(arg) ((arg) == CCAPP_SERVICE_CMD ? "CCAPP_SERVICE_CMD" : \
|
|
(arg) == CCAPP_CREATE_SESSION ? "CCAPP_CREATE_SESSION" : \
|
|
(arg) == CCAPP_CLOSE_SESSION ? "CCAPP_CLOSE_SESSION" : \
|
|
(arg) == CCAPP_INVOKE_FEATURE ? "CCAPP_INVOKE_FEATURE" : \
|
|
(arg) == CCAPP_SESSION_UPDATE ? "CCAPP_SESSION_UPDATE" : \
|
|
(arg) == CCAPP_FEATURE_UPDATE ? "CCAPP_FEATURE_UPDATE" : \
|
|
(arg) == CCAPP_UPDATELINES ? "CCAPP_UPDATELINES" : \
|
|
(arg) == CCAPP_FAILOVER_IND ? "CCAPP_FAILOVER_IND" : \
|
|
(arg) == CCAPP_FALLBACK_IND ? "CCAPP_FALLBACK_IND" : \
|
|
(arg) == CCAPP_MODE_NOTIFY ? "CCAPP_MODE_NOTIFY" : \
|
|
(arg) == CCAPP_SHUTDOWN_ACK ? "CCAPP_SHUTDOWN_ACK" : \
|
|
(arg) == CCAPP_REG_ALL_FAIL ? "CCAPP_REG_ALL_FAIL" : \
|
|
(arg) == CCAPP_INVOKEPROVIDER_FEATURE ? "CCAPP_INVOKEPROVIDER_FEATURE" : \
|
|
(arg) == CCAPP_SEND_INFO ? "CCAPP_SEND_INFO" : \
|
|
(arg) == CCAPP_RCVD_INFO ? "CCAPP_RCVD_INFO" : \
|
|
(arg) == CCAPP_LOGOUT_RESET ? "CCAPP_LOGOUT_RESET" : \
|
|
(arg) == CCAPP_SESSION_MGMT ? "CCAPP_SESSION_MGMT" : \
|
|
(arg) == CCAPP_THREAD_UNLOAD ? "CCAPP_THREAD_UNLOAD" : \
|
|
(arg) == CCAPP_SESSION_MGMT ? "CCAPP_SESSION_MGMT" : \
|
|
"Unknown Cmd")
|
|
|
|
#define APP_ERR_MSG err_msg
|
|
|
|
#define MAX_REASON_LENGTH MAX_SIP_REASON_LENGTH
|
|
#define MAX_SESSION_PARAM_LEN 128
|
|
|
|
/* UNKNOWN_PHRASE_STR should equal the value returned
|
|
* if the phrase code is not found in the dictionary.
|
|
* For CIUS, this is found in LocalizedStrings.java */
|
|
#define UNKNOWN_PHRASE_STR "???"
|
|
#define UNKNOWN_PHRASE_STR_SIZE 3
|
|
|
|
/*---------------------------------------------------------
|
|
*
|
|
* Local Variables
|
|
*
|
|
*/
|
|
|
|
/*---------------------------------------------------------
|
|
*
|
|
* Global Variables
|
|
*
|
|
*/
|
|
static CCAppGlobal_t gCCApp;
|
|
cc_int32_t g_CCAppDebug=TRUE;
|
|
cc_int32_t g_CCLogDebug=TRUE;
|
|
cc_int32_t g_NotifyCallDebug=TRUE;
|
|
cc_int32_t g_NotifyLineDebug=TRUE;
|
|
|
|
cc_srv_ctrl_req_t reset_type;
|
|
|
|
extern cprMsgQueue_t ccapp_msgq;
|
|
extern cprThread_t ccapp_thread;
|
|
extern boolean platform_initialized;
|
|
extern void resetReady();
|
|
extern void resetNotReady();
|
|
extern int sendResetUpdates;
|
|
|
|
extern boolean apply_config;
|
|
|
|
extern char g_new_signaling_ip[];
|
|
|
|
extern int configFileDownloadNeeded;
|
|
cc_action_t pending_action_type = NO_ACTION;
|
|
|
|
|
|
/*--------------------------------------------------------------------------
|
|
* External function prototypes
|
|
*--------------------------------------------------------------------------
|
|
*/
|
|
extern void send_protocol_config_msg(void);
|
|
extern void gsm_shutdown(void);
|
|
extern void sip_shutdown(void);
|
|
extern void dp_shutdown(void);
|
|
extern void MiscAppTaskShutdown(void);
|
|
extern void lsm_init(void);
|
|
extern void fsm_init(void);
|
|
extern void fim_init(void);
|
|
extern void SIPTaskPostRestart(boolean restart);
|
|
extern void ccsip_register_cancel(boolean cancel_reg, boolean backup_proxy);
|
|
extern void notify_register_update(int last_available_line);
|
|
extern void getLineIdAndCallId (line_t *line_id, callid_t *call_id);
|
|
extern void set_default_video_pref(int pref);
|
|
extern void set_next_sess_video_pref(int pref);
|
|
extern void cc_media_update_native_video_support(boolean val);
|
|
extern void cc_media_update_video_cap(boolean val);
|
|
extern void cc_media_update_video_txcap(boolean val);
|
|
|
|
session_data_t * getDeepCopyOfSessionData(session_data_t *data);
|
|
static void ccappUpdateSessionData(session_update_t *sessUpd);
|
|
static void ccappFeatureUpdated (feature_update_t *featUpd);
|
|
void destroy_ccapp_thread();
|
|
void ccpro_handleserviceControlNotify();
|
|
|
|
/*---------------------------------------------------------
|
|
*
|
|
* Function declarations
|
|
*
|
|
*/
|
|
|
|
cc_service_state_t mapProviderState(cc_reg_state_t state)
|
|
{
|
|
switch(state) {
|
|
case CC_INSERVICE:
|
|
return CC_STATE_INS;
|
|
case CC_CREATED_IDLE:
|
|
return CC_STATE_IDLE;
|
|
case CC_OOS_REGISTERING:
|
|
case CC_OOS_FAILOVER:
|
|
case CC_OOS_IDLE:
|
|
default:
|
|
return CC_STATE_OOS;
|
|
|
|
}
|
|
}
|
|
|
|
static void ccapp_hlapi_update_device_reg_state() {
|
|
g_deviceInfo.ins_state = mapProviderState(gCCApp.state);
|
|
g_deviceInfo.ins_cause = gCCApp.cause;
|
|
g_deviceInfo.cucm_mode = gCCApp.mode;
|
|
ccsnap_gen_deviceEvent(CCAPI_DEVICE_EV_STATE, CC_DEVICE_ID);
|
|
}
|
|
|
|
void ccpro_handleINS() {
|
|
registration_processEvent(EV_CC_INSERVICE);
|
|
}
|
|
|
|
void ccpro_handleOOS() {
|
|
switch(gCCApp.cause){
|
|
case CC_CAUSE_REG_ALL_FAILED:
|
|
registration_processEvent(EV_CC_OOS_REG_ALL_FAILED);
|
|
break;
|
|
case CC_CAUSE_FAILOVER:
|
|
registration_processEvent(EV_CC_OOS_FAILOVER);
|
|
break;
|
|
case CC_CAUSE_FALLBACK:
|
|
registration_processEvent(EV_CC_OOS_FALLBACK);
|
|
break;
|
|
case CC_CAUSE_SHUTDOWN:
|
|
registration_processEvent(EV_CC_OOS_SHUTDOWN_ACK);
|
|
break;
|
|
}
|
|
}
|
|
|
|
cc_boolean is_action_to_be_deferred(cc_action_t action) {
|
|
if (CCAPI_DeviceInfo_isPhoneIdle(CC_DEVICE_ID) == FALSE) {
|
|
pending_action_type = action;
|
|
DEF_DEBUG("Action deferred=%d", action);
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
void perform_deferred_action() {
|
|
cc_action_t temp_action = pending_action_type;
|
|
|
|
if (is_action_to_be_deferred(pending_action_type) == TRUE) {
|
|
return;
|
|
}
|
|
|
|
pending_action_type = NO_ACTION;
|
|
DEF_DEBUG("Perform deferred action=%d", temp_action);
|
|
|
|
if (temp_action == RESET_ACTION || temp_action == RESTART_ACTION) {
|
|
ccpro_handleserviceControlNotify();
|
|
} else if (temp_action == RE_REGISTER_ACTION) {
|
|
CCAPI_Service_reregister(g_dev_hdl, g_dev_name, g_cfg_p, g_compl_cfg);
|
|
} else if (temp_action == STOP_ACTION) {
|
|
CCAPI_Service_stop();
|
|
} else if (temp_action == DESTROY_ACTION) {
|
|
CCAPI_Service_destroy();
|
|
}
|
|
}
|
|
|
|
void ccpro_handleserviceControlNotify() {
|
|
cc_action_t temp_action = NO_ACTION;
|
|
if (reset_type == CC_DEVICE_RESET) {
|
|
temp_action = RESET_ACTION;
|
|
} else if (reset_type == CC_DEVICE_RESTART) {
|
|
temp_action = RESTART_ACTION;
|
|
}
|
|
|
|
if ((reset_type != CC_DEVICE_ICMP_UNREACHABLE) &&
|
|
is_action_to_be_deferred(temp_action) == TRUE) {
|
|
return;
|
|
}
|
|
|
|
|
|
if (reset_type == CC_DEVICE_RESET) {
|
|
resetRequest();
|
|
} else if (reset_type == CC_DEVICE_RESTART) {
|
|
registration_processEvent(EV_CC_DO_SOFT_RESET);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the registration state
|
|
*/
|
|
cc_reg_state_t ccapp_get_state() {
|
|
return gCCApp.state;
|
|
}
|
|
|
|
void ccp_handler(void* msg, int type);
|
|
|
|
/**
|
|
*
|
|
* CCApp Provider init routine.
|
|
*
|
|
* @param none
|
|
*
|
|
* @return void
|
|
*
|
|
* @pre None
|
|
*/
|
|
void CCAppInit()
|
|
{
|
|
ccProvider_state_t srvcState;
|
|
appListener handler = ccp_handler;
|
|
|
|
gCCApp.state = CC_CREATED_IDLE;
|
|
gCCApp.cause = CC_CAUSE_NONE;
|
|
gCCApp.mode = CC_MODE_INVALID;
|
|
gCCApp.cucm_mode = NONE_AVAIL;
|
|
if (platThreadInit("CCApp_Task") != 0) {
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Adjust relative priority of CCApp thread.
|
|
*/
|
|
(void) cprAdjustRelativeThreadPriority(CCPROVIDER_THREAD_RELATIVE_PRIORITY);
|
|
|
|
debug_bind_keyword("cclog", &g_CCLogDebug);
|
|
srvcState.cause = gCCApp.cause; // XXX set but not used
|
|
srvcState.mode = gCCApp.mode; // XXX set but not used
|
|
(void) srvcState;
|
|
|
|
//Add listeners
|
|
//CCProvider lister
|
|
DEF_DEBUG(DEB_F_PREFIX"Add ccp listener: type%d", DEB_F_PREFIX_ARGS(SIP_CC_PROV, "CCAppInit"),
|
|
CCAPP_CCPROVIER);
|
|
|
|
addCcappListener(&handler, CCAPP_CCPROVIER);
|
|
|
|
}
|
|
|
|
/*
|
|
* Function: processProviderEvent
|
|
*
|
|
* Description: inform session events to CCApp
|
|
*
|
|
* Parameters:
|
|
* call_id - call identifier
|
|
* line_id - line identifier
|
|
*
|
|
* Returns: none
|
|
*/
|
|
void
|
|
processProviderEvent (line_t line_id, unsigned int event, int data)
|
|
{
|
|
static const char fname[] = "processProviderEvent";
|
|
callid_t call_id = 0;
|
|
|
|
DEF_DEBUG(DEB_F_PREFIX"line=%d event=%d data=%d", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname),
|
|
line_id, event, data);
|
|
switch(event) {
|
|
case DEVICE_FEATURE_CFWD:
|
|
getLineIdAndCallId(&line_id, &call_id);
|
|
if (lsm_is_line_available(line_id, FALSE) == FALSE) {
|
|
//Send onhook to indicate session closure.
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_STATE, CREATE_CALL_HANDLE(line_id, call_id));
|
|
lsm_ui_display_notify_str_index(STR_INDEX_ERROR_PASS_LIMIT);
|
|
break;
|
|
}
|
|
|
|
cc_feature(CC_SRC_UI, call_id, line_id, CC_FEATURE_CFWD_ALL, NULL);
|
|
|
|
break;
|
|
case DEVICE_SUPPORTS_NATIVE_VIDEO:
|
|
cc_media_update_native_video_support(data);
|
|
break;
|
|
case DEVICE_ENABLE_VIDEO:
|
|
cc_media_update_video_cap(data);
|
|
break;
|
|
case DEVICE_ENABLE_CAMERA:
|
|
cc_media_update_native_video_txcap(data);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Function: CheckAndGetAvailableLine
|
|
*
|
|
* Parameters:
|
|
* line - line identifier
|
|
* call - call identifier
|
|
*
|
|
* Returns: TRUE if a line is available.
|
|
*/
|
|
static boolean CheckAndGetAvailableLine(line_t *line, callid_t *call)
|
|
{
|
|
/*
|
|
* case 1: line>0 & call>0: invoking this in an offhook session.
|
|
* case 2: line>0 & call=0: invoking this onhook with simple filter active
|
|
* case 3: line=0 & call=0: invoking this in onhook with all calls filter active
|
|
*/
|
|
if ((*line > 0) && (*call == 0)) {
|
|
if (lsm_is_line_available(*line, FALSE) == FALSE) {
|
|
// since the session is not created yet, no need to close the session.
|
|
lsm_ui_display_notify_str_index(STR_INDEX_ERROR_PASS_LIMIT);
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if ((*line == 0) && (*call == 0)) {
|
|
*line = lsm_get_available_line(FALSE);
|
|
if (*line == 0 ) {
|
|
// since the session is not created yet, no need to close the session.
|
|
lsm_ui_display_notify_str_index(STR_INDEX_ERROR_PASS_LIMIT);
|
|
return FALSE;
|
|
}
|
|
}
|
|
*call = (*call == 0) ? cc_get_new_call_id() : *call;
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* Function: getVideoPref
|
|
*
|
|
* Description: get video direction if specified
|
|
*
|
|
* Parameters:
|
|
* data - urn param
|
|
*
|
|
* Returns: sdp_direction_e - requested video direction
|
|
*/
|
|
sdp_direction_e getVideoPref( string_t data)
|
|
{
|
|
if ( data == NULL ) {
|
|
return SDP_MAX_QOS_DIRECTIONS;
|
|
}
|
|
|
|
if ( strstr(data, "video=sendrecv")) {
|
|
return SDP_DIRECTION_SENDRECV;
|
|
} else if (strstr(data, "video=sendonly")) {
|
|
return SDP_DIRECTION_SENDONLY;
|
|
} else if (strstr(data, "video=recvonly")){
|
|
return SDP_DIRECTION_RECVONLY;
|
|
} else if (strstr(data, "video=none")){
|
|
return SDP_DIRECTION_INACTIVE;
|
|
} else {
|
|
return SDP_MAX_QOS_DIRECTIONS;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Function: updateSessionVideoPref
|
|
*
|
|
* Description: update video direction for the session only
|
|
*
|
|
* Parameters:
|
|
* line_id - line at which the session needs the video pref updated
|
|
* call_id - callid for which the session needs the video pref updated
|
|
* dir - video pref
|
|
*
|
|
* Returns:
|
|
*/
|
|
static void updateSessionVideoPref( line_t line_id, callid_t call_id, sdp_direction_e video_pref)
|
|
{
|
|
static const char fname[] = "updateSessionVideoPref";
|
|
cc_feature_data_t featdata;
|
|
|
|
DEF_DEBUG(DEB_L_C_F_PREFIX"updating to %d video capapbility %s",
|
|
DEB_L_C_F_PREFIX_ARGS(SIP_CC_PROV, call_id, line_id, fname), video_pref,
|
|
(video_pref == SDP_DIRECTION_INACTIVE ? "disabled" : "enabled"));
|
|
featdata.caps.support_direction = video_pref;
|
|
cc_feature(CC_SRC_UI, call_id, line_id, CC_FEATURE_UPD_SESSION_MEDIA_CAP, &featdata);
|
|
}
|
|
|
|
/*
|
|
* Function: updateVideoPref
|
|
*
|
|
* Description: update video direction if specified
|
|
*
|
|
* Parameters:
|
|
* line_id - line at which the session needs the video pref updated
|
|
* call_id - callid for which the session needs the video pref updated
|
|
* data - urn param
|
|
*
|
|
* Returns:
|
|
*/
|
|
|
|
static void updateVideoPref( unsigned int event, line_t line_id, callid_t call_id, sdp_direction_e video_pref/*string_t data*/)
|
|
{
|
|
static const char fname[] = "updateVideoPref";
|
|
|
|
if ( video_pref == SDP_MAX_QOS_DIRECTIONS ) {
|
|
// we are done no updates needed
|
|
return;
|
|
}
|
|
|
|
switch (event) {
|
|
case CC_FEATURE_UPD_SESSION_MEDIA_CAP:
|
|
if ( call_id == CC_NO_CALL_ID ) {
|
|
// This is the only means to update the default behavior
|
|
set_default_video_pref(video_pref);
|
|
} else {
|
|
updateSessionVideoPref(line_id, call_id, video_pref);
|
|
}
|
|
break;
|
|
case CC_FEATURE_DIALSTR:
|
|
case CC_FEATURE_DIAL:
|
|
case CC_FEATURE_SPEEDDIAL:
|
|
case CC_FEATURE_REDIAL:
|
|
if ( call_id == CC_NO_CALL_ID ) {
|
|
set_next_sess_video_pref(video_pref);
|
|
} else {
|
|
updateSessionVideoPref(line_id, call_id, video_pref);
|
|
}
|
|
break;
|
|
case CC_FEATURE_NEW_CALL:
|
|
case CC_FEATURE_OFFHOOK:
|
|
case CC_FEATURE_CONF:
|
|
case CC_FEATURE_B2BCONF:
|
|
case CC_FEATURE_XFER:
|
|
set_next_sess_video_pref(video_pref);
|
|
break;
|
|
case CC_FEATURE_RESUME:
|
|
case CC_FEATURE_ANSWER:
|
|
updateSessionVideoPref(line_id, call_id, video_pref);
|
|
break;
|
|
default:
|
|
CCAPP_DEBUG(DEB_L_C_F_PREFIX"event=%d. update to %d not supported",
|
|
DEB_L_C_F_PREFIX_ARGS(SIP_CC_PROV, call_id, line_id, fname), event, video_pref);
|
|
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Function: getDigits
|
|
*
|
|
* Description: returns the first param before the ;
|
|
*
|
|
* Parameters:
|
|
* data - urn param
|
|
* digits - memory to return the first param
|
|
* Returns:
|
|
*/
|
|
void getDigits(string_t data, char *digits) {
|
|
char *endptr;
|
|
int len=0;
|
|
|
|
digits[0]=0;
|
|
|
|
if ( data !=NULL ) {
|
|
endptr = strchr(data,';');
|
|
if ( endptr ) {
|
|
len = endptr - data;
|
|
} else {
|
|
len = strlen(data);
|
|
}
|
|
|
|
if ( len) {
|
|
memcpy(digits, data, len);
|
|
digits[len] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Function: processSessionEvent
|
|
*
|
|
* Description: inform session events to CCApp
|
|
*
|
|
* Parameters:
|
|
* call_id - call identifier
|
|
* line_id - line identifier
|
|
*
|
|
* Returns: none
|
|
*/
|
|
void
|
|
processSessionEvent (line_t line_id, callid_t call_id, unsigned int event, sdp_direction_e video_pref, ccSession_feature_t ccData)
|
|
{
|
|
static const char fname[] = "processSessionEvent";
|
|
cc_feature_data_t featdata;
|
|
int instance = line_id;
|
|
boolean incoming = FALSE;
|
|
session_data_t * sess_data_p;
|
|
char digits[CC_MAX_DIALSTRING_LEN];
|
|
char* data = (char*)ccData.info;
|
|
char* data1 =(char*)ccData.info1;
|
|
long strtol_result;
|
|
char *strtol_end;
|
|
|
|
CCAPP_DEBUG(DEB_L_C_F_PREFIX"event=%d data=%s",
|
|
DEB_L_C_F_PREFIX_ARGS(SIP_CC_PROV, call_id, line_id, fname), event,
|
|
((event == CC_FEATURE_KEYPRESS) ? "..." : data));
|
|
|
|
memset(&featdata, 0, sizeof(cc_feature_data_t));
|
|
updateVideoPref(event, line_id, call_id, video_pref);
|
|
switch(event) {
|
|
case CC_FEATURE_ONHOOK:
|
|
getLineIdAndCallId(&line_id, &call_id);
|
|
CCAPP_DEBUG(DEB_F_PREFIX"CC_FEATURE_ONHOOK = %s\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), data);
|
|
cc_onhook_ext(CC_SRC_UI, call_id, line_id, FALSE,
|
|
(data && (strncasecmp(data, "ACTIVECALLS", sizeof("ACTIVECALLS")) == 0))?
|
|
CC_REASON_ACTIVECALL_LIST: CC_REASON_NULL );
|
|
break;
|
|
case CC_FEATURE_KEYPRESS:
|
|
dp_int_update_keypress(line_id, call_id, (unsigned char)*data);
|
|
break;
|
|
case CC_FEATURE_BKSPACE:
|
|
dp_int_update_keypress(line_id, call_id, BKSP_KEY);
|
|
break;
|
|
case CC_FEATURE_CREATEOFFER:
|
|
featdata.session.sessionid = ccData.sessionid;
|
|
featdata.session.has_constraints = ccData.has_constraints;
|
|
cc_createoffer (CC_SRC_UI, CC_SRC_GSM, call_id, (line_t)instance, CC_FEATURE_CREATEOFFER, &featdata);
|
|
break;
|
|
case CC_FEATURE_CREATEANSWER:
|
|
featdata.session.sessionid = ccData.sessionid;
|
|
featdata.session.has_constraints = ccData.has_constraints;
|
|
cc_createanswer (CC_SRC_UI, CC_SRC_GSM, call_id, (line_t)instance, CC_FEATURE_CREATEANSWER, data, &featdata);
|
|
break;
|
|
case CC_FEATURE_SETLOCALDESC:
|
|
cc_setlocaldesc (CC_SRC_UI, CC_SRC_GSM, call_id, (line_t)instance, CC_FEATURE_SETLOCALDESC, ccData.action, data, &featdata);
|
|
break;
|
|
case CC_FEATURE_SETREMOTEDESC:
|
|
cc_setremotedesc (CC_SRC_UI, CC_SRC_GSM, call_id, (line_t)instance, CC_FEATURE_SETREMOTEDESC, ccData.action, data, &featdata);
|
|
break;
|
|
case CC_FEATURE_SETPEERCONNECTION:
|
|
PR_ASSERT(strlen(data) < PC_HANDLE_SIZE);
|
|
if (strlen(data) >= PC_HANDLE_SIZE)
|
|
return;
|
|
|
|
sstrncpy(featdata.pc.pc_handle, data, sizeof(featdata.pc.pc_handle));
|
|
|
|
cc_int_feature2(CC_MSG_SETPEERCONNECTION, CC_SRC_UI, CC_SRC_GSM,
|
|
call_id, (line_t)instance,
|
|
CC_FEATURE_SETPEERCONNECTION, &featdata);
|
|
break;
|
|
case CC_FEATURE_ADDSTREAM:
|
|
featdata.track.stream_id = ccData.stream_id;
|
|
featdata.track.track_id = ccData.track_id;
|
|
featdata.track.media_type = ccData.media_type;
|
|
cc_int_feature2(CC_MSG_ADDSTREAM, CC_SRC_UI, CC_SRC_GSM, call_id, (line_t)instance, CC_FEATURE_ADDSTREAM, &featdata);
|
|
break;
|
|
case CC_FEATURE_REMOVESTREAM:
|
|
featdata.track.stream_id = ccData.stream_id;
|
|
featdata.track.track_id = ccData.track_id;
|
|
featdata.track.media_type = ccData.media_type;
|
|
cc_int_feature2(CC_MSG_REMOVESTREAM, CC_SRC_UI, CC_SRC_GSM, call_id, (line_t)instance, CC_FEATURE_REMOVESTREAM, &featdata);
|
|
break;
|
|
case CC_FEATURE_ADDICECANDIDATE:
|
|
featdata.candidate.level = ccData.level;
|
|
sstrncpy(featdata.candidate.candidate, data, sizeof(featdata.candidate.candidate)-1);
|
|
sstrncpy(featdata.candidate.mid, data1, sizeof(featdata.candidate.mid)-1);
|
|
cc_int_feature2(CC_MSG_ADDCANDIDATE, CC_SRC_UI, CC_SRC_GSM, call_id, (line_t)instance, CC_FEATURE_ADDICECANDIDATE, &featdata);
|
|
break;
|
|
case CC_FEATURE_DIALSTR:
|
|
if (CheckAndGetAvailableLine(&line_id, &call_id) == TRUE) {
|
|
getDigits(data, digits);
|
|
if (strlen(digits) == 0) {
|
|
//if dial string is empty then go offhook
|
|
cc_offhook(CC_SRC_UI, call_id, line_id);
|
|
} else {
|
|
dp_int_init_dialing_data(line_id, call_id);
|
|
dp_int_dial_immediate(line_id, call_id, TRUE,
|
|
(char *)digits, NULL, CC_MONITOR_NONE);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CC_FEATURE_DIAL:
|
|
dp_int_dial_immediate(line_id, call_id, FALSE, NULL, NULL, CC_MONITOR_NONE);
|
|
break;
|
|
case CC_FEATURE_SPEEDDIAL:
|
|
/*
|
|
* BLF Pickup Line Selection:
|
|
* -------------------------
|
|
*
|
|
* case 1: line_id>0 & call_id>0 : BLF key press after going offhook on a given line.
|
|
* Check if the given line has available call capacity. If not, end the session
|
|
* and display STR_INDEX_NO_LINE_FOR_PICKUP toast.
|
|
*
|
|
* case 2: line_id>0 & call_id=0 : BLF key press w/o offhook when a simple filter is active.
|
|
* Check if the given line has available call capacity. If not, find the next available line.
|
|
* If no available line is found, display STR_INDEX_NO_LINE_FOR_PICKUP toast.
|
|
*
|
|
* case 3: line_id=0 & call_id=0 : BLF key press w/o offhook when a AllCalls filter is active.
|
|
* Find an available line. If no available line is found,
|
|
* display STR_INDEX_NO_LINE_FOR_PICKUP toast.
|
|
*/
|
|
if (strncmp(data, CISCO_BLFPICKUP_STRING, (sizeof(CISCO_BLFPICKUP_STRING) - 1)) == 0) {
|
|
if ((instance > 0) && (call_id > 0)) {
|
|
if (lsm_is_line_available(instance, incoming) == FALSE) {
|
|
session_update_t sessUpd;
|
|
sessUpd.eventID = CALL_STATE;
|
|
sessUpd.sessionID = createSessionId(line_id, call_id);
|
|
sessUpd.sessType = SESSIONTYPE_CALLCONTROL;
|
|
sessUpd.update.ccSessionUpd.data.state_data.state = evOnHook;
|
|
sessUpd.update.ccSessionUpd.data.state_data.line_id = line_id;
|
|
sessUpd.update.ccSessionUpd.data.state_data.cause = CC_CAUSE_NORMAL;
|
|
ccappUpdateSessionData(&sessUpd);
|
|
// Pass this update to Session Manager
|
|
lsm_ui_display_notify_str_index(STR_INDEX_NO_LINE_FOR_PICKUP);
|
|
break;
|
|
}
|
|
}
|
|
else if ((instance > 0) && (call_id == 0)) {
|
|
if (lsm_is_line_available(instance, incoming) == FALSE) {
|
|
line_id = lsm_get_available_line(incoming);
|
|
if (line_id == 0 ) {
|
|
// since the session is not created yet, no need to close the session.
|
|
lsm_ui_display_notify_str_index(STR_INDEX_NO_LINE_FOR_PICKUP);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if ((instance == 0) && (call_id == 0)) {
|
|
line_id = lsm_get_available_line(incoming);
|
|
if (line_id == 0 ) {
|
|
// since the session is not created yet, no need to close the session.
|
|
lsm_ui_display_notify_str_index(STR_INDEX_NO_LINE_FOR_PICKUP);
|
|
break;
|
|
}
|
|
}
|
|
call_id = (call_id == 0) ? cc_get_new_call_id() : call_id;
|
|
}
|
|
/*
|
|
* SpeedDial Line Selection:
|
|
* ------------------------
|
|
*
|
|
* case 1: line_id>0 & call_id>0 : speeddial key press after going offhook on a given line.
|
|
* Simply use this line to make an outgoing call.
|
|
*
|
|
* case 2: line_id>0 & call_id=0 : SD key press w/o offhook when a simple filter is active.
|
|
* Check if the given line has available call capacity. If not,
|
|
* display STR_INDEX_ERROR_PASS_LIMIT toast.
|
|
*
|
|
* case 3: line_id=0 & call_id=0 : SD key press w/o offhook when a AllCalls filter is active.
|
|
* Find an available line. If no available line is found,
|
|
* display STR_INDEX_ERROR_PASS_LIMIT toast.
|
|
*/
|
|
else if (CheckAndGetAvailableLine(&line_id, &call_id) == FALSE) {
|
|
break;
|
|
}
|
|
|
|
getDigits(data,digits);
|
|
|
|
dp_int_init_dialing_data(line_id, call_id);
|
|
dp_int_dial_immediate(line_id, call_id, TRUE,
|
|
digits, NULL, CC_MONITOR_NONE);
|
|
break;
|
|
case CC_FEATURE_BLIND_XFER_WITH_DIALSTRING:
|
|
featdata.xfer.cause = CC_CAUSE_XFER_LOCAL_WITH_DIALSTRING;
|
|
sstrncpy(featdata.xfer.dialstring, (char *)data, CC_MAX_DIALSTRING_LEN);
|
|
cc_feature(CC_SRC_UI, call_id, (line_t)instance, CC_FEATURE_BLIND_XFER,
|
|
&featdata);
|
|
break;
|
|
case CC_FEATURE_REDIAL:
|
|
if (line_id == 0) {
|
|
/*
|
|
* If line_id is zero, get the last dialed line.
|
|
*/
|
|
line_id = dp_get_redial_line();
|
|
if (line_id == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* if not an existing call, check capacity on the line */
|
|
if (call_id == CC_NO_CALL_ID) {
|
|
if (lsm_is_line_available(line_id, FALSE) == FALSE) {
|
|
/*
|
|
* since the session is not created yet, no
|
|
* need to close the session.
|
|
*/
|
|
lsm_ui_display_notify_str_index(STR_INDEX_ERROR_PASS_LIMIT);
|
|
break;
|
|
} else {
|
|
/* we have capacity and call does not exist */
|
|
call_id = cc_get_new_call_id();
|
|
}
|
|
}
|
|
dp_int_do_redial(line_id, call_id);
|
|
break;
|
|
|
|
case CC_FEATURE_UPD_SESSION_MEDIA_CAP:
|
|
/* handled in updateVideoPref() just outside of the switch */
|
|
break;
|
|
|
|
case CC_FEATURE_NEW_CALL:
|
|
case CC_FEATURE_OFFHOOK:
|
|
if (lsm_is_line_available(line_id, FALSE) == FALSE) {
|
|
//close the session
|
|
CCAPP_DEBUG(DEB_F_PREFIX"CC_FEATURE_OFFHOOK: no available line.\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_STATE, CREATE_CALL_HANDLE(line_id, call_id));
|
|
lsm_ui_display_notify_str_index(STR_INDEX_ERROR_PASS_LIMIT);
|
|
break;
|
|
}
|
|
|
|
if (call_id == 0) {
|
|
call_id = cc_get_new_call_id();
|
|
} else {
|
|
if (event == CC_FEATURE_NEW_CALL) {
|
|
CCAPP_DEBUG(DEB_F_PREFIX"CC_FEATURE_NEW_CALL called with callid=%d\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), call_id);
|
|
} else {
|
|
CCAPP_DEBUG(DEB_F_PREFIX"CC_FEATURE_OFFHOOK called with callid=%d\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), call_id);
|
|
}
|
|
}
|
|
cc_offhook(CC_SRC_UI, call_id, line_id);
|
|
break;
|
|
|
|
case CC_FEATURE_CFWD_ALL:
|
|
getLineIdAndCallId(&line_id, &call_id);
|
|
|
|
cc_feature(CC_SRC_UI, call_id, line_id, CC_FEATURE_CFWD_ALL, NULL);
|
|
|
|
break;
|
|
|
|
case CC_FEATURE_RESUME:
|
|
case CC_FEATURE_ANSWER:
|
|
|
|
sess_data_p = (session_data_t *)findhash(createSessionId(line_id, call_id));
|
|
if ( sess_data_p == NULL ) {
|
|
break;
|
|
}
|
|
if (sess_data_p->state == HOLD || sess_data_p->state == HOLDREVERT) {
|
|
cc_feature(CC_SRC_UI, call_id, line_id, CC_FEATURE_RESUME, NULL);
|
|
} else {
|
|
cc_feature(CC_SRC_UI, call_id, line_id, event, NULL);
|
|
}
|
|
break;
|
|
|
|
case CC_FEATURE_END_CALL:
|
|
CCAPP_DEBUG(DEB_F_PREFIX"CC_FEATURE_ONHOOK = %s\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), data);
|
|
if (data && (strcmp(data, "ACTIVECALLS") == 0)) {
|
|
getLineIdAndCallId(&line_id, &call_id);
|
|
cc_onhook_ext(CC_SRC_UI, call_id, line_id, TRUE, CC_REASON_ACTIVECALL_LIST);
|
|
} else {
|
|
cc_feature(CC_SRC_UI, call_id, line_id, event, NULL);
|
|
}
|
|
break;
|
|
|
|
case CC_FEATURE_CONF:
|
|
// for CUCM mode we will translate CONF to B2BCONF
|
|
if ( gCCApp.mode == CC_MODE_CCM ) {
|
|
if ( gCCApp.mode == CC_MODE_CCM && platGetFeatureAllowed(CC_SIS_B2B_CONF) ) {
|
|
//CUCME can't support B2BCONF currently.
|
|
event = CC_FEATURE_B2BCONF;
|
|
}
|
|
}// DON'T ADD BREAK HERE. EVENT IS PASSED BELOW
|
|
case CC_FEATURE_B2BCONF:
|
|
case CC_FEATURE_XFER:
|
|
getDigits(data,digits);
|
|
if ( strlen(digits)) {
|
|
cc_feature_data_t ftr_data;
|
|
CCAPP_DEBUG(DEB_F_PREFIX"conf: sid=%s.\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname),data);
|
|
// if data is received we need to extract the call id
|
|
// and send target_call_id in feature_data
|
|
// Post the event on the original call ( received call id as string in data).
|
|
if ( event == CC_FEATURE_B2BCONF ) {
|
|
ftr_data.b2bconf.target_call_id = call_id;
|
|
} else if ( event == CC_FEATURE_XFER ) {
|
|
ftr_data.xfer.target_call_id = call_id;
|
|
} else if ( event == CC_FEATURE_CONF) {
|
|
//Legacy local conference.
|
|
ftr_data.cnf.target_call_id = call_id;
|
|
}
|
|
|
|
errno = 0;
|
|
strtol_result = strtol(digits, &strtol_end, 10);
|
|
|
|
if (errno || digits == strtol_end || strtol_result < INT_MIN || strtol_result > INT_MAX) {
|
|
CCAPP_ERROR(DEB_F_PREFIX"digits parse error %s.\n",DEB_F_PREFIX_ARGS(SIP_CC_PROV, __FUNCTION__), digits);
|
|
} else {
|
|
cc_feature(CC_SRC_UI, GET_CALLID((int) strtol_result), line_id, event, &ftr_data);
|
|
}
|
|
break;
|
|
} else {
|
|
CCAPP_DEBUG(DEB_F_PREFIX"conf: no sid.\n",DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
|
}// DON'T ADD BREAK HERE. EVENT IS PASSED BELOW
|
|
|
|
case CC_FEATURE_B2B_JOIN:
|
|
case CC_FEATURE_DIRTRXFR:
|
|
case CC_FEATURE_SELECT:
|
|
case CC_FEATURE_CANCEL:
|
|
cc_feature(CC_SRC_UI, call_id, line_id, event, NULL);
|
|
break;
|
|
|
|
case CC_FEATURE_HOLD:
|
|
if (data && ((strcmp(data, "TRANSFER") == 0) ||
|
|
(strcmp(data, "CONFERENCE") == 0) || (strcmp(data, "SWAP") == 0))) {
|
|
featdata.hold.call_info.data.hold_resume_reason = CC_REASON_SWAP;
|
|
} else {
|
|
|
|
featdata.hold.call_info.data.hold_resume_reason = CC_REASON_NONE;
|
|
}
|
|
featdata.hold.call_info.type = CC_FEAT_HOLD;
|
|
featdata.hold.msg_body.num_parts = 0;
|
|
cc_feature(CC_SRC_UI, call_id, line_id, event, &featdata);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CCAppShutdown()
|
|
{
|
|
}
|
|
|
|
|
|
static char * ccapp_cmd_to_str(unsigned int cmd) {
|
|
switch (cmd) {
|
|
case CMD_INSERVICE:
|
|
return "CMD_INSERVICE";
|
|
case CMD_SHUTDOWN:
|
|
return "CMD_SHUTDOWN";
|
|
case CMD_RESTART:
|
|
return "CMD_RESTART";
|
|
case CMD_UNREGISTER_ALL_LINES:
|
|
return "CMD_UNREGISTER_ALL_LINES";
|
|
case CMD_REGISTER_ALL_LINES:
|
|
return "CMD_REGISTER_ALL_LINES";
|
|
default:
|
|
return "CMD_UNKNOWN";
|
|
}
|
|
}
|
|
/**
|
|
*
|
|
* CC Provider process service Cmds
|
|
*
|
|
* @param cmd - Command
|
|
* @param reason - reason
|
|
* @param reasonStr - reason string
|
|
*
|
|
* @return void
|
|
*
|
|
* @pre None
|
|
*/
|
|
void CCApp_processCmds(unsigned int cmd, unsigned int reason, string_t reasonStr)
|
|
{
|
|
static const char fname[] = "CCApp_processCmds";
|
|
CCAPP_DEBUG(DEB_F_PREFIX" Received Cmd %s\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV,
|
|
fname), ccapp_cmd_to_str(cmd));
|
|
switch (cmd) {
|
|
case CMD_INSERVICE:
|
|
ccsnap_device_init();
|
|
ccsnap_line_init();
|
|
gCCApp.state = CC_OOS_REGISTERING;
|
|
send_protocol_config_msg();
|
|
break;
|
|
case CMD_SHUTDOWN:
|
|
case CMD_UNREGISTER_ALL_LINES:
|
|
/* send a shutdown message to the SIP Task */
|
|
SIPTaskPostShutdown(SIP_EXTERNAL, reason, reasonStr);
|
|
break;
|
|
case CMD_RESTART:
|
|
SIPTaskPostRestart(TRUE);
|
|
break;
|
|
case CMD_BLF_INIT:
|
|
pres_sub_handler_initialized();
|
|
break;
|
|
default:
|
|
APP_ERR_MSG("CCApp_processCmds: Error: Unknown message %d\n", cmd);
|
|
break;
|
|
}
|
|
}
|
|
|
|
boolean isNoCallExist()
|
|
{
|
|
hashItr_t itr;
|
|
|
|
hashItrInit(&itr);
|
|
|
|
return (hashItrNext(&itr)?FALSE:TRUE);
|
|
}
|
|
|
|
/**
|
|
* Make deep copy of session_data_t
|
|
*/
|
|
session_data_t * getDeepCopyOfSessionData(session_data_t *data)
|
|
{
|
|
session_data_t *newData = (session_data_t *) cpr_malloc(sizeof(session_data_t));
|
|
|
|
if ( newData != NULL ) {
|
|
memset(newData, 0, sizeof(session_data_t));
|
|
|
|
if ( data != NULL ) {
|
|
*newData = *data;
|
|
newData->ref_count = 1;
|
|
newData->clg_name = strlib_copy(data->clg_name);
|
|
newData->clg_number = strlib_copy(data->clg_number);
|
|
newData->cld_name = strlib_copy(data->cld_name);
|
|
newData->cld_number = strlib_copy(data->cld_number);
|
|
newData->alt_number = strlib_copy(data->alt_number);
|
|
newData->orig_called_name = strlib_copy(data->orig_called_name);
|
|
newData->orig_called_number = strlib_copy(data->orig_called_number);
|
|
newData->last_redir_name = strlib_copy(data->last_redir_name);
|
|
newData->last_redir_number = strlib_copy(data->last_redir_number);
|
|
newData->plcd_name = strlib_copy(data->plcd_name);
|
|
newData->plcd_number = strlib_copy(data->plcd_number);
|
|
newData->status = strlib_copy(data->status);
|
|
calllogger_copy_call_log(&newData->call_log, &data->call_log);
|
|
} else {
|
|
newData->ref_count = 1;
|
|
newData->state = ONHOOK;
|
|
newData->security = CC_SECURITY_NONE;
|
|
newData->policy = CC_POLICY_NONE;
|
|
newData->clg_name = strlib_empty();
|
|
newData->clg_number = strlib_empty();
|
|
newData->cld_name = strlib_empty();
|
|
newData->cld_number = strlib_empty();
|
|
newData->alt_number = strlib_empty();
|
|
newData->orig_called_name = strlib_empty();
|
|
newData->orig_called_number = strlib_empty();
|
|
newData->last_redir_name = strlib_empty();
|
|
newData->last_redir_number = strlib_empty();
|
|
newData->plcd_name = strlib_empty();
|
|
newData->plcd_number = strlib_empty();
|
|
newData->status = strlib_empty();
|
|
calllogger_init_call_log(&newData->call_log);
|
|
}
|
|
|
|
}
|
|
return newData;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
* CCApp Provider search for session and deepfree data
|
|
*
|
|
* @return ptr to session data
|
|
*
|
|
* @pre None
|
|
*/
|
|
|
|
void cleanSessionData(session_data_t *data)
|
|
{
|
|
if ( data != NULL ) {
|
|
strlib_free(data->clg_name);
|
|
data->clg_name = strlib_empty();
|
|
strlib_free(data->clg_number);
|
|
data->clg_number = strlib_empty();
|
|
strlib_free(data->alt_number);
|
|
data->alt_number = strlib_empty();
|
|
strlib_free(data->cld_name);
|
|
data->cld_name = strlib_empty();
|
|
strlib_free(data->cld_number);
|
|
data->cld_number = strlib_empty();
|
|
strlib_free(data->orig_called_name);
|
|
data->orig_called_name = strlib_empty();
|
|
strlib_free(data->orig_called_number);
|
|
data->orig_called_number = strlib_empty();
|
|
strlib_free(data->last_redir_name);
|
|
data->last_redir_name = strlib_empty();
|
|
strlib_free(data->last_redir_number);
|
|
data->last_redir_number = strlib_empty();
|
|
strlib_free(data->plcd_name);
|
|
data->plcd_name = strlib_empty();
|
|
strlib_free(data->plcd_number);
|
|
data->plcd_number = strlib_empty();
|
|
strlib_free(data->status);
|
|
data->status = strlib_empty();
|
|
calllogger_free_call_log(&data->call_log);
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* CCApp Provider check for CONNECTED calls for preservation
|
|
*
|
|
* @return boolean - do we need to move in call preservation phase
|
|
*
|
|
* @pre None
|
|
*/
|
|
|
|
boolean ccappPreserveCall()
|
|
{
|
|
static const char fname[] = "ccappPreserveCall";
|
|
hashItr_t itr;
|
|
session_data_t *data;
|
|
boolean retVal = FALSE;
|
|
|
|
CCAPP_DEBUG(DEB_F_PREFIX"called\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
|
hashItrInit(&itr);
|
|
while ( (data = (session_data_t*)hashItrNext(&itr)) != NULL ) {
|
|
if ( data->state == CONNECTED || data->state == PRESERVATION ) {
|
|
// need to wait for this call to end.
|
|
CCAPP_DEBUG(DEB_F_PREFIX"inPreservation = true\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
|
gCCApp.inPreservation = TRUE;
|
|
gCCApp.preservID = data->sess_id;
|
|
capset_get_allowed_features(gCCApp.mode, PRESERVATION, data->allowed_features);
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_PRESERVATION, CREATE_CALL_HANDLE_FROM_SESSION_ID(data->sess_id));
|
|
retVal = TRUE;
|
|
} else {
|
|
// End this call now
|
|
CCAPP_DEBUG(DEB_F_PREFIX"ending call %x\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), data->sess_id);
|
|
/*
|
|
* Note that for calls in state such as RIU, HOLD etc.
|
|
* we must send ON hook event (cc_onhook) instead of
|
|
* CC_FEATURE_END_CALL because corrsponding state machines
|
|
* handle only onhook event to clean up calls.
|
|
*/
|
|
cc_onhook(CC_SRC_UI, GET_CALLID(data->sess_id),
|
|
GET_LINEID(data->sess_id), TRUE);
|
|
|
|
}
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* CCApp Provider check if its safe to proceed with failover/fallback
|
|
*
|
|
* @return void - do we need to move in call preservation phase
|
|
*
|
|
* @pre None
|
|
*/
|
|
|
|
void proceedWithFOFB()
|
|
{
|
|
static const char fname[] = "proceedWithFOFB";
|
|
|
|
CCAPP_DEBUG(DEB_F_PREFIX"called. preservation=%d in cucm mode=%s \n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname),
|
|
gCCApp.inPreservation,
|
|
gCCApp.cucm_mode == FAILOVER ? "FAILOVER":
|
|
gCCApp.cucm_mode == FALLBACK ? "FALLBACK":
|
|
gCCApp.cucm_mode == NO_CUCM_SRST_AVAILABLE ?
|
|
"NO_CUCM_SRST_AVAILABLE": "NONE");
|
|
gCCApp.state = CC_OOS_REGISTERING;
|
|
|
|
switch(gCCApp.cucm_mode)
|
|
{
|
|
case FAILOVER:
|
|
cc_fail_fallback_sip(CC_SRC_UI, RSP_START, CC_REG_FAILOVER_RSP, TRUE);
|
|
gCCApp.cause = CC_CAUSE_FAILOVER;
|
|
break;
|
|
|
|
case FALLBACK:
|
|
cc_fail_fallback_sip(CC_SRC_UI, RSP_START, CC_REG_FALLBACK_RSP, TRUE);
|
|
gCCApp.cause = CC_CAUSE_FALLBACK;
|
|
break;
|
|
|
|
case NO_CUCM_SRST_AVAILABLE:
|
|
gCCApp.cause = CC_CAUSE_REG_ALL_FAILED;
|
|
gCCApp.state = CC_OOS_IDLE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// Notify OOS state to Session Manager
|
|
switch (mapProviderState(gCCApp.state)) {
|
|
case CC_STATE_OOS:
|
|
ccpro_handleOOS();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
ccapp_hlapi_update_device_reg_state();
|
|
}
|
|
/**
|
|
*
|
|
* ccappHandleRegUpdates handles reg state changes.
|
|
*
|
|
* @param featUpd - feature update with reg state msg
|
|
*
|
|
* @return void
|
|
*
|
|
* @pre None
|
|
*/
|
|
void ccappHandleRegStateUpdates(feature_update_t *featUpd)
|
|
{
|
|
static const char fname[] = "ccappHandleRegStateUpdates";
|
|
|
|
CCAPP_DEBUG(DEB_F_PREFIX"called. feature=%d=%s, state=%d\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), featUpd->featureID, CCAPP_TASK_CMD_PRINT(featUpd->featureID), gCCApp.state);
|
|
gCCApp.cause = CC_CAUSE_NONE;
|
|
|
|
// Update state varaibles to track state
|
|
switch (featUpd->featureID)
|
|
{
|
|
case CCAPP_MODE_NOTIFY:
|
|
gCCApp.mode = featUpd->update.ccFeatUpd.data.line_info.info;
|
|
CCAPP_DEBUG(DEB_F_PREFIX"called. gCCApp.mode= %d gCCApp.state=%d. Returning\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), gCCApp.mode, gCCApp.state);
|
|
return;
|
|
|
|
case CCAPP_FAILOVER_IND:
|
|
gCCApp.state = CC_OOS_FAILOVER;
|
|
gCCApp.cucm_mode = FAILOVER;
|
|
gCCApp.cause = CC_CAUSE_FAILOVER;
|
|
if ( featUpd->update.ccFeatUpd.data.line_info.info == CC_TYPE_CCM ){
|
|
gCCApp.mode = CC_MODE_CCM;
|
|
}
|
|
|
|
else if (featUpd->update.ccFeatUpd.data.line_info.info == 3) {
|
|
gCCApp.mode = CC_MODE_NONCCM;
|
|
}
|
|
|
|
if ( ccappPreserveCall() == FALSE) {
|
|
gCCApp.state = CC_OOS_REGISTERING;
|
|
cc_fail_fallback_sip(CC_SRC_UI, RSP_START, CC_REG_FAILOVER_RSP, FALSE);
|
|
}
|
|
break;
|
|
|
|
case CCAPP_FALLBACK_IND:
|
|
gCCApp.cucm_mode = FALLBACK;
|
|
if ( featUpd->update.ccFeatUpd.data.line_info.info == CC_TYPE_CCM ){
|
|
gCCApp.mode = CC_MODE_CCM;
|
|
}
|
|
if ( isNoCallExist() ) {
|
|
gCCApp.state = CC_OOS_REGISTERING;
|
|
gCCApp.cause = CC_CAUSE_FALLBACK;
|
|
cc_fail_fallback_sip(CC_SRC_UI, RSP_START, CC_REG_FALLBACK_RSP, FALSE);
|
|
}
|
|
break;
|
|
|
|
case CCAPP_SHUTDOWN_ACK:
|
|
gCCApp.state = CC_OOS_IDLE;
|
|
gCCApp.cucm_mode = NONE_AVAIL;
|
|
gCCApp.inPreservation = FALSE;
|
|
gCCApp.cause = CC_CAUSE_SHUTDOWN;
|
|
|
|
break;
|
|
case CCAPP_REG_ALL_FAIL:
|
|
gCCApp.state = CC_OOS_IDLE;
|
|
gCCApp.cucm_mode = NO_CUCM_SRST_AVAILABLE;
|
|
gCCApp.inPreservation = FALSE;
|
|
if (ccappPreserveCall() == FALSE) {
|
|
gCCApp.cause = CC_CAUSE_REG_ALL_FAILED;
|
|
} else {
|
|
gCCApp.cause = CC_CAUSE_FAILOVER;
|
|
}
|
|
break;
|
|
|
|
case CCAPP_LOGOUT_RESET:
|
|
gCCApp.state = CC_OOS_IDLE;
|
|
gCCApp.cucm_mode = NONE_AVAIL;
|
|
/*gCCApp.inFailover = FALSE;
|
|
gCCApp.inFallback = FALSE;*/
|
|
gCCApp.inPreservation = FALSE;
|
|
gCCApp.cause = CC_CAUSE_LOGOUT_RESET;
|
|
break;
|
|
}
|
|
// Notify INS/OOS state to Session Manager if required
|
|
CCAPP_DEBUG(DEB_F_PREFIX"called. service_state=%d, mode=%d, cause=%d\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname),
|
|
mapProviderState(gCCApp.state),
|
|
gCCApp.mode,
|
|
gCCApp.cause);
|
|
switch (mapProviderState(gCCApp.state)) {
|
|
case CC_STATE_INS:
|
|
ccpro_handleINS();
|
|
break;
|
|
case CC_STATE_OOS:
|
|
ccpro_handleOOS();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
ccapp_hlapi_update_device_reg_state();
|
|
}
|
|
|
|
/*
|
|
* this function determine if the called number (i.e., dialed number) contains
|
|
* string x-cisco-serviceuri-cfwdall.
|
|
*/
|
|
static boolean ccappCldNumIsCfwdallString(string_t cld_number) {
|
|
static char cfwdAllString[STATUS_LINE_MAX_LEN] = "x-cisco-serviceuri-cfwdall";
|
|
|
|
if (strncmp(cld_number, cfwdAllString, strlen(cfwdAllString)) == 0) {
|
|
/* The Called Party number is the Call Forward all URI */
|
|
return ((int) TRUE);
|
|
}
|
|
return ((int) FALSE);
|
|
}
|
|
|
|
/**
|
|
* Api to update mute state of connected call
|
|
*/
|
|
cc_call_handle_t ccappGetConnectedCall(){
|
|
session_data_t * data;
|
|
hashItr_t itr;
|
|
|
|
hashItrInit(&itr);
|
|
while ( (data = (session_data_t*)hashItrNext(&itr)) != NULL ) {
|
|
if( data->state == CONNECTED ) {
|
|
return CREATE_CALL_HANDLE_FROM_SESSION_ID(data->sess_id);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* CCApp Provider cache session data to hashTable routine
|
|
*
|
|
* @param sessUpd - Session update from CC
|
|
*
|
|
* @return void
|
|
*
|
|
* @pre None
|
|
*/
|
|
|
|
static void ccappUpdateSessionData (session_update_t *sessUpd)
|
|
{
|
|
static const char fname[] = "ccappUpdateSessionData";
|
|
session_data_t * data = (session_data_t *)findhash(sessUpd->sessionID), *sess_data_p;
|
|
boolean createdSessionData = TRUE;
|
|
cc_deviceinfo_ref_t handle = 0;
|
|
boolean previouslyInConference = FALSE;
|
|
|
|
if ( data == NULL ) {
|
|
cc_call_state_t call_state = sessUpd->update.ccSessionUpd.data.state_data.state;
|
|
|
|
if ( ( sessUpd->eventID == CALL_INFORMATION ) ||
|
|
( sessUpd->eventID == CALL_STATE || sessUpd->eventID == CALL_NEWCALL
|
|
|| sessUpd->eventID == CREATE_OFFER || sessUpd->eventID == CREATE_ANSWER
|
|
|| sessUpd->eventID == SET_LOCAL_DESC || sessUpd->eventID == SET_REMOTE_DESC
|
|
|| sessUpd->eventID == REMOTE_STREAM_ADD)) {
|
|
|
|
CCAPP_DEBUG(DEB_F_PREFIX"CALL_SESSION_CREATED for session id 0x%x event is 0x%x \n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), sessUpd->sessionID,
|
|
sessUpd->eventID);
|
|
|
|
if (sessUpd->eventID == CALL_INFORMATION ) {
|
|
call_state = RINGIN;
|
|
|
|
} else {
|
|
if ( sessUpd->update.ccSessionUpd.data.state_data.state == ONHOOK ) {
|
|
CCAPP_DEBUG(DEB_F_PREFIX"NOT CREATING Session Ignoring event %d sessid %x as state is ONHOOK\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), sessUpd->eventID, sessUpd->sessionID );
|
|
//Even session data is not created, we need to send ONHOOK to application to terminate call.
|
|
createdSessionData = FALSE;
|
|
}
|
|
call_state = sessUpd->update.ccSessionUpd.data.state_data.state;
|
|
}
|
|
//Create a new call.
|
|
if (createdSessionData == TRUE) {
|
|
cc_call_handle_t callHandle = CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID);
|
|
//<Added for automation test purpose, <CallBegin>
|
|
NOTIFY_CALL_DEBUG(DEB_NOTIFY_PREFIX"[line=%d][call.ref=%d]\n",
|
|
"CallBegin", GET_LINE_ID(callHandle), GET_CALL_ID(callHandle));
|
|
//>
|
|
data = cpr_malloc(sizeof(session_data_t));
|
|
if ( data == NULL ) {
|
|
APP_ERR_MSG("ccappUpdateSessionData Error: cpr_malloc failed for session data\n");
|
|
return;
|
|
}
|
|
//Populate the session hash data the first time.
|
|
memset(data, 0, sizeof(session_data_t));
|
|
data->sess_id = sessUpd->sessionID;
|
|
data->state = call_state;
|
|
data->line = sessUpd->update.ccSessionUpd.data.state_data.line_id;
|
|
if (sessUpd->eventID == CALL_NEWCALL || sessUpd->eventID == CREATE_OFFER ||
|
|
sessUpd->eventID == CREATE_ANSWER || sessUpd->eventID == SET_LOCAL_DESC ||
|
|
sessUpd->eventID == SET_REMOTE_DESC || sessUpd->eventID == REMOTE_STREAM_ADD ) {
|
|
data->attr = sessUpd->update.ccSessionUpd.data.state_data.attr;
|
|
data->inst = sessUpd->update.ccSessionUpd.data.state_data.inst;
|
|
}
|
|
data->cause = sessUpd->update.ccSessionUpd.data.state_data.cause;
|
|
data->clg_name = strlib_empty();
|
|
data->clg_number = strlib_empty();
|
|
data->alt_number = strlib_empty();
|
|
data->cld_name = strlib_empty();
|
|
data->cld_number = strlib_empty();
|
|
data->orig_called_name = strlib_empty();
|
|
data->orig_called_number = strlib_empty();
|
|
data->last_redir_name = strlib_empty();
|
|
data->last_redir_number = strlib_empty();
|
|
data->plcd_name = strlib_empty();
|
|
data->plcd_number = strlib_empty();
|
|
data->status = strlib_empty();
|
|
data->gci[0] = 0;
|
|
data->vid_dir = SDP_DIRECTION_INACTIVE;
|
|
data->callref = 0;
|
|
calllogger_init_call_log(&data->call_log);
|
|
|
|
if ( sessUpd->eventID == CREATE_OFFER || sessUpd->eventID == CREATE_ANSWER
|
|
|| sessUpd->eventID == SET_LOCAL_DESC || sessUpd->eventID == SET_REMOTE_DESC
|
|
|| sessUpd->eventID == REMOTE_STREAM_ADD) {
|
|
data->sdp = sessUpd->update.ccSessionUpd.data.state_data.sdp;
|
|
data->cause = sessUpd->update.ccSessionUpd.data.state_data.cause;
|
|
data->media_stream_track_id = sessUpd->update.ccSessionUpd.data.state_data.media_stream_track_id;
|
|
data->media_stream_id = sessUpd->update.ccSessionUpd.data.state_data.media_stream_id;
|
|
}
|
|
|
|
/*
|
|
* If phone was idle, we not going to active state
|
|
* send notification to resetmanager that we
|
|
* are no longer resetReady.
|
|
*/
|
|
if ((CCAPI_DeviceInfo_isPhoneIdle(handle) == TRUE) && (sendResetUpdates)) {
|
|
resetNotReady();
|
|
}
|
|
(void) addhash(data->sess_id, data);
|
|
}
|
|
|
|
//The update accordingly
|
|
switch (sessUpd->eventID) {
|
|
case CALL_INFORMATION:
|
|
data->clg_name = ccsnap_EscapeStrToLocaleStr(data->clg_name, sessUpd->update.ccSessionUpd.data.call_info.clgName, LEN_UNKNOWN);
|
|
data->cld_name = ccsnap_EscapeStrToLocaleStr(data->cld_name, sessUpd->update.ccSessionUpd.data.call_info.cldName, LEN_UNKNOWN);
|
|
data->orig_called_name = ccsnap_EscapeStrToLocaleStr(data->orig_called_name, sessUpd->update.ccSessionUpd.data.call_info.origCalledName, LEN_UNKNOWN);
|
|
data->last_redir_name = ccsnap_EscapeStrToLocaleStr(data->last_redir_name, sessUpd->update.ccSessionUpd.data.call_info.lastRedirectingName, LEN_UNKNOWN);
|
|
|
|
data->clg_number = strlib_update(data->clg_number, sessUpd->update.ccSessionUpd.data.call_info.clgNumber);
|
|
data->cld_number = strlib_update(data->cld_number, sessUpd->update.ccSessionUpd.data.call_info.cldNumber);
|
|
data->alt_number = strlib_update(data->alt_number, sessUpd->update.ccSessionUpd.data.call_info.altClgNumber);
|
|
data->orig_called_number = strlib_update(data->orig_called_number, sessUpd->update.ccSessionUpd.data.call_info.origCalledNumber);
|
|
data->last_redir_number = strlib_update(data->last_redir_number, sessUpd->update.ccSessionUpd.data.call_info.lastRedirectingNumber);
|
|
data->type = sessUpd->update.ccSessionUpd.data.call_info.call_type;
|
|
data->inst = sessUpd->update.ccSessionUpd.data.call_info.instance_id;
|
|
data->security = sessUpd->update.ccSessionUpd.data.call_info.security;
|
|
data->policy = sessUpd->update.ccSessionUpd.data.call_info.policy;
|
|
break;
|
|
case CALL_STATE:
|
|
if (createdSessionData == FALSE) {
|
|
return;
|
|
}
|
|
data->state = sessUpd->update.ccSessionUpd.data.state_data.state;
|
|
data->line = sessUpd->update.ccSessionUpd.data.state_data.line_id;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else if (sessUpd->eventID == CALL_DELETE_LAST_DIGIT) {
|
|
CCAPP_DEBUG(DEB_F_PREFIX"CALL_DELETE_LAST_DIGIT: event %d sessid %x.\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), sessUpd->eventID, sessUpd->sessionID );
|
|
return;
|
|
} else {
|
|
CCAPP_DEBUG(DEB_F_PREFIX"NOT CREATING Session Ignoring event %d sessid %x \n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), sessUpd->eventID, sessUpd->sessionID );
|
|
return;
|
|
}
|
|
|
|
// send event to csf2g API
|
|
if (data != NULL) {
|
|
capset_get_allowed_features(gCCApp.mode, data->state, data->allowed_features);
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_CREATED, CREATE_CALL_HANDLE_FROM_SESSION_ID(data->sess_id));
|
|
}
|
|
return;
|
|
|
|
}
|
|
|
|
CCAPP_DEBUG(DEB_F_PREFIX"Found data for sessid %x event %d\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), sessUpd->sessionID, sessUpd->eventID);
|
|
switch(sessUpd->eventID) {
|
|
case CALL_SESSION_CLOSED:
|
|
// find and deep free then delete
|
|
sess_data_p = (session_data_t *)findhash(sessUpd->sessionID);
|
|
if ( sess_data_p != NULL ){
|
|
cleanSessionData(sess_data_p);
|
|
if ( 0 > delhash(sessUpd->sessionID) ) {
|
|
APP_ERR_MSG (DEB_F_PREFIX"failed to delete hash sessid=0x%08x\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname),sessUpd->sessionID);
|
|
}
|
|
cpr_free(sess_data_p);
|
|
}
|
|
if ( (gCCApp.inPreservation || (gCCApp.cucm_mode == FALLBACK)) && isNoCallExist()) {
|
|
/* The phone is now Idle. Clear the inPreservation Flag */
|
|
gCCApp.inPreservation = FALSE;
|
|
proceedWithFOFB();
|
|
}
|
|
if ((CCAPI_DeviceInfo_isPhoneIdle(handle) == TRUE) && (sendResetUpdates)) {
|
|
resetReady();
|
|
}
|
|
if (pending_action_type != NO_ACTION) {
|
|
perform_deferred_action();
|
|
}
|
|
break;
|
|
|
|
case CALL_STATE:
|
|
DEF_DEBUG(DEB_F_PREFIX"Call_STATE:. state=%d, attr=%d, cause=%d, instance=%d\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname),
|
|
sessUpd->update.ccSessionUpd.data.state_data.state,
|
|
data->attr,
|
|
sessUpd->update.ccSessionUpd.data.state_data.cause,
|
|
data->inst);
|
|
if ( sessUpd->update.ccSessionUpd.data.state_data.state == HOLD &&
|
|
(data->state == REMHOLD || data->state == REMINUSE)){
|
|
data->state = REMHOLD;
|
|
} else {
|
|
data->state = sessUpd->update.ccSessionUpd.data.state_data.state;
|
|
}
|
|
data->line = sessUpd->update.ccSessionUpd.data.state_data.line_id;
|
|
sessUpd->update.ccSessionUpd.data.state_data.attr = data->attr;
|
|
sessUpd->update.ccSessionUpd.data.state_data.inst = data->inst;
|
|
|
|
data->cause = sessUpd->update.ccSessionUpd.data.state_data.cause;
|
|
|
|
//Update call state
|
|
if ( data != NULL ){
|
|
capset_get_allowed_features(gCCApp.mode, data->state, data->allowed_features);
|
|
}
|
|
calllogger_update(data);
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_STATE, CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
|
|
//<Added for automation test purpose, <CallEnd>
|
|
if (data->state == ONHOOK) {
|
|
NOTIFY_CALL_DEBUG(DEB_NOTIFY_PREFIX"[line=%d][call.ref=%d]\n",
|
|
"CallEND", data->line, data->id);
|
|
}
|
|
//>
|
|
|
|
if (data->state == ONHOOK) {
|
|
// find and deep free then delete
|
|
sess_data_p = (session_data_t *)findhash(sessUpd->sessionID);
|
|
if ( sess_data_p != NULL ){
|
|
cleanSessionData(sess_data_p);
|
|
if ( 0 > delhash(sessUpd->sessionID) ) {
|
|
APP_ERR_MSG (DEB_F_PREFIX"failed to delete hash sessid=0x%08x\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname),sessUpd->sessionID);
|
|
}
|
|
cpr_free(sess_data_p);
|
|
data = NULL;
|
|
}
|
|
if ((gCCApp.inPreservation || (gCCApp.cucm_mode == FALLBACK)) && isNoCallExist()) {
|
|
/* The phone is now Idle. Clear the inPreservation Flag */
|
|
gCCApp.inPreservation = FALSE;
|
|
proceedWithFOFB();
|
|
}
|
|
if ((CCAPI_DeviceInfo_isPhoneIdle(handle) == TRUE) && (sendResetUpdates)) {
|
|
resetReady();
|
|
}
|
|
if (pending_action_type != NO_ACTION) {
|
|
perform_deferred_action();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CALL_CALLREF:
|
|
data->callref = sessUpd->update.ccSessionUpd.data.callref;
|
|
break;
|
|
case CALL_GCID:
|
|
if ( ! strncasecmp(data->gci, sessUpd->update.ccSessionUpd.data.gcid, CC_MAX_GCID)) {
|
|
// No change in gci we can ignore the update
|
|
return;
|
|
}
|
|
sstrncpy(data->gci, sessUpd->update.ccSessionUpd.data.gcid, CC_MAX_GCID);
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_GCID, CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
break;
|
|
case CALL_NEWCALL:
|
|
data->state = sessUpd->update.ccSessionUpd.data.state_data.state;
|
|
data->line = sessUpd->update.ccSessionUpd.data.state_data.line_id;
|
|
data->attr = sessUpd->update.ccSessionUpd.data.state_data.attr;
|
|
data->inst = sessUpd->update.ccSessionUpd.data.state_data.inst;
|
|
return;
|
|
break;
|
|
|
|
case CALL_ATTR:
|
|
data->attr = sessUpd->update.ccSessionUpd.data.state_data.attr;
|
|
calllogger_update(data);
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_ATTR, CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
break;
|
|
|
|
case CALL_INFORMATION:
|
|
// check conference state, if it changes, we'll send a conference event notification
|
|
previouslyInConference = CCAPI_CallInfo_getIsConference(data);
|
|
|
|
data->clg_name = ccsnap_EscapeStrToLocaleStr(data->clg_name, sessUpd->update.ccSessionUpd.data.call_info.clgName, LEN_UNKNOWN);
|
|
data->cld_name = ccsnap_EscapeStrToLocaleStr(data->cld_name, sessUpd->update.ccSessionUpd.data.call_info.cldName, LEN_UNKNOWN);
|
|
data->orig_called_name = ccsnap_EscapeStrToLocaleStr(data->orig_called_name, sessUpd->update.ccSessionUpd.data.call_info.origCalledName, LEN_UNKNOWN);
|
|
data->last_redir_name = ccsnap_EscapeStrToLocaleStr(data->last_redir_name, sessUpd->update.ccSessionUpd.data.call_info.lastRedirectingName, LEN_UNKNOWN);
|
|
data->clg_number = strlib_update(data->clg_number, sessUpd->update.ccSessionUpd.data.call_info.clgNumber);
|
|
data->cld_number = strlib_update(data->cld_number, sessUpd->update.ccSessionUpd.data.call_info.cldNumber);
|
|
data->alt_number = strlib_update(data->alt_number, sessUpd->update.ccSessionUpd.data.call_info.altClgNumber);
|
|
data->orig_called_number = strlib_update(data->orig_called_number, sessUpd->update.ccSessionUpd.data.call_info.origCalledNumber);
|
|
data->last_redir_number = strlib_update(data->last_redir_number, sessUpd->update.ccSessionUpd.data.call_info.lastRedirectingNumber);
|
|
data->type = sessUpd->update.ccSessionUpd.data.call_info.call_type;
|
|
data->inst = sessUpd->update.ccSessionUpd.data.call_info.instance_id;
|
|
data->security = sessUpd->update.ccSessionUpd.data.call_info.security;
|
|
data->policy = sessUpd->update.ccSessionUpd.data.call_info.policy;
|
|
if ((data->cld_number[0]) && ccappCldNumIsCfwdallString(data->cld_number)) {
|
|
DEF_DEBUG(DEB_F_PREFIX"Not updating the UI. Called Number = %s\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), data->cld_number);
|
|
return;
|
|
}
|
|
/*
|
|
* For 3rd Gen and 4th Gen phones... Use sessUpd->update structure to pass call information
|
|
* For 5th Gen phones, the information will be localized by a 5th Gen Application, and the
|
|
* dictionaries might not be equivalent.
|
|
*/
|
|
calllogger_update(data);
|
|
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_CALLINFO, CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
|
|
// if we're entering a conference, then indicate conference participant info (in case the info came earlier, app
|
|
// will receive the notification now. If info comes later, then app will receive an additional subsequent info notice
|
|
// at that time.
|
|
if ((!previouslyInConference) && (CCAPI_CallInfo_getIsConference(data))) {
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_CONF_PARTICIPANT_INFO, CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
}
|
|
|
|
break;
|
|
|
|
case CALL_PLACED_INFO:
|
|
data->plcd_number = strlib_update(data->plcd_number, sessUpd->update.ccSessionUpd.data.plcd_info.cldNum);
|
|
data->plcd_name = ccsnap_EscapeStrToLocaleStr(data->plcd_name, sessUpd->update.ccSessionUpd.data.plcd_info.cldName, LEN_UNKNOWN);
|
|
calllogger_setPlacedCallInfo(data);
|
|
|
|
break;
|
|
|
|
case CALL_SELECTED:
|
|
data->isSelected = sessUpd->update.ccSessionUpd.data.action;
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_SELECT, CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
break;
|
|
|
|
case CALL_SELECT_FEATURE_SET:
|
|
// Not quite perfect but should do for now
|
|
if ( strcmp("CONNECTEDNOFEAT", sessUpd->update.ccSessionUpd.data.feat_set.featSet ) ) {
|
|
data->allowed_features[CCAPI_CALL_CAP_HOLD] = FALSE;
|
|
data->allowed_features[CCAPI_CALL_CAP_CONFERENCE] = FALSE;
|
|
data->allowed_features[CCAPI_CALL_CAP_TRANSFER] = FALSE;
|
|
} else if ( sessUpd->update.ccSessionUpd.data.feat_set.featMask[0] == skConfrn ) {
|
|
data->allowed_features[CCAPI_CALL_CAP_CONFERENCE] = FALSE;
|
|
}
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_CAPABILITY, CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
break;
|
|
|
|
case CALL_STATUS:
|
|
/*
|
|
* For 5th Gen Phones, data->status is localized.
|
|
* 3rd Gen and 4th Gen phones should use sessUpd->update struct to pass the status to the application.
|
|
*/
|
|
data->status = ccsnap_EscapeStrToLocaleStr(data->status, sessUpd->update.ccSessionUpd.data.status.status, LEN_UNKNOWN);
|
|
if (data->status != NULL) {
|
|
if(strncmp(data->status, UNKNOWN_PHRASE_STR, UNKNOWN_PHRASE_STR_SIZE) == 0){
|
|
data->status = strlib_empty();
|
|
}
|
|
if(strcmp(data->status, strlib_empty()) != 0){
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_STATUS, CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
}
|
|
}
|
|
//<Added for automation test purpose, <CallStatusChanged>
|
|
NOTIFY_CALL_DEBUG(DEB_NOTIFY_PREFIX"[line=%d][call.ref=%d][status=%s]\n",
|
|
"callStatusChange", data->line, data->id,
|
|
NOTIFY_CALL_STATUS);
|
|
//>
|
|
|
|
break;
|
|
if(strcmp(data->status, strlib_empty()) != 0){
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_STATUS, CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
}
|
|
|
|
case CALL_PRESERVATION_ACTIVE:
|
|
data->state = PRESERVATION;
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_PRESERVATION, CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
break;
|
|
|
|
case RINGER_STATE:
|
|
data->ringer_start = sessUpd->update.ccSessionUpd.data.ringer.start;
|
|
data->ringer_mode = sessUpd->update.ccSessionUpd.data.ringer.mode;
|
|
data->ringer_once = sessUpd->update.ccSessionUpd.data.ringer.once;
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_RINGER_STATE, CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
break;
|
|
|
|
case VIDEO_AVAIL:
|
|
if ( data->vid_dir == sessUpd->update.ccSessionUpd.data.action ) {
|
|
// no change don't update
|
|
return;
|
|
}
|
|
data->vid_dir = sessUpd->update.ccSessionUpd.data.action;
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_VIDEO_AVAIL, CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
break;
|
|
case VIDEO_OFFERED:
|
|
data->vid_offer = sessUpd->update.ccSessionUpd.data.action;
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_VIDEO_OFFERED, CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
break;
|
|
case CALL_ENABLE_BKSP:
|
|
data->allowed_features[CCAPI_CALL_CAP_BACKSPACE] = TRUE;
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_CAPABILITY, CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
break;
|
|
case CALL_SECURITY:
|
|
data->security = sessUpd->update.ccSessionUpd.data.security;
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_SECURITY, CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
break;
|
|
case CALL_LOGDISP:
|
|
data->log_disp = sessUpd->update.ccSessionUpd.data.action;
|
|
calllogger_updateLogDisp(data);
|
|
// No need to generate this event anymore
|
|
// ccsnap_gen_callEvent(CCAPI_CALL_EV_LOG_DISP, CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
break;
|
|
case CALL_DELETE_LAST_DIGIT:
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_LAST_DIGIT_DELETED, CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
break;
|
|
case CALL_FEATURE_CANCEL:
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_XFR_OR_CNF_CANCELLED, CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
break;
|
|
case CALL_RECV_INFO_LIST:
|
|
//Should not come here. It's dealed in CCAPP_RCVD_INFO.
|
|
break;
|
|
case MEDIA_INTERFACE_UPDATE_BEGIN:
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_MEDIA_INTERFACE_UPDATE_BEGIN,
|
|
CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
break;
|
|
case MEDIA_INTERFACE_UPDATE_SUCCESSFUL:
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_MEDIA_INTERFACE_UPDATE_SUCCESSFUL,
|
|
CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
break;
|
|
case MEDIA_INTERFACE_UPDATE_FAIL:
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_MEDIA_INTERFACE_UPDATE_FAIL,
|
|
CREATE_CALL_HANDLE_FROM_SESSION_ID(sessUpd->sessionID));
|
|
break;
|
|
case CREATE_OFFER:
|
|
case CREATE_ANSWER:
|
|
case SET_LOCAL_DESC:
|
|
case SET_REMOTE_DESC:
|
|
case REMOTE_STREAM_ADD:
|
|
data->sdp = sessUpd->update.ccSessionUpd.data.state_data.sdp;
|
|
data->cause = sessUpd->update.ccSessionUpd.data.state_data.cause;
|
|
data->state = sessUpd->update.ccSessionUpd.data.state_data.state;
|
|
data->media_stream_track_id = sessUpd->update.ccSessionUpd.data.state_data.media_stream_track_id;
|
|
data->media_stream_id = sessUpd->update.ccSessionUpd.data.state_data.media_stream_id;
|
|
capset_get_allowed_features(gCCApp.mode, data->state, data->allowed_features);
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_STATE, CREATE_CALL_HANDLE_FROM_SESSION_ID(data->sess_id));
|
|
break;
|
|
default:
|
|
DEF_DEBUG(DEB_F_PREFIX"Unknown event, id = %d\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), sessUpd->eventID);
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void freeSessionData(session_update_t *sessUpd)
|
|
{
|
|
switch(sessUpd->eventID) {
|
|
case CALL_INFORMATION:
|
|
strlib_free(sessUpd->update.ccSessionUpd.data.call_info.clgName);
|
|
strlib_free(sessUpd->update.ccSessionUpd.data.call_info.clgNumber);
|
|
strlib_free(sessUpd->update.ccSessionUpd.data.call_info.cldName);
|
|
strlib_free(sessUpd->update.ccSessionUpd.data.call_info.cldNumber);
|
|
strlib_free(sessUpd->update.ccSessionUpd.data.call_info.altClgNumber);
|
|
strlib_free(sessUpd->update.ccSessionUpd.data.call_info.origCalledName);
|
|
strlib_free(sessUpd->update.ccSessionUpd.data.call_info.origCalledNumber);
|
|
strlib_free(sessUpd->update.ccSessionUpd.data.call_info.lastRedirectingName);
|
|
strlib_free(sessUpd->update.ccSessionUpd.data.call_info.lastRedirectingNumber);
|
|
break;
|
|
case CALL_PLACED_INFO:
|
|
strlib_free(sessUpd->update.ccSessionUpd.data.plcd_info.cldName);
|
|
strlib_free(sessUpd->update.ccSessionUpd.data.plcd_info.cldNum);
|
|
break;
|
|
case CALL_SELECT_FEATURE_SET:
|
|
strlib_free(sessUpd->update.ccSessionUpd.data.feat_set.featSet);
|
|
break;
|
|
case CALL_STATUS:
|
|
strlib_free(sessUpd->update.ccSessionUpd.data.status.status);
|
|
break;
|
|
case CALL_RECV_INFO_LIST:
|
|
strlib_free(sessUpd->update.ccSessionUpd.data.recv_info_list);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void freeSessionMgmtData(session_mgmt_t *sessMgmt)
|
|
{
|
|
switch(sessMgmt->func_id) {
|
|
case SESSION_MGMT_APPLY_CONFIG:
|
|
strlib_free(sessMgmt->data.config.log_server);
|
|
strlib_free(sessMgmt->data.config.load_server);
|
|
strlib_free(sessMgmt->data.config.load_id);
|
|
strlib_free(sessMgmt->data.config.inactive_load_id);
|
|
strlib_free(sessMgmt->data.config.cucm_result);
|
|
strlib_free(sessMgmt->data.config.fcp_version_stamp);
|
|
strlib_free(sessMgmt->data.config.dialplan_version_stamp);
|
|
strlib_free(sessMgmt->data.config.config_version_stamp);
|
|
break;
|
|
case SESSION_MGMT_EXECUTE_URI:
|
|
strlib_free(sessMgmt->data.uri.uri);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void freeRcvdInfo(session_rcvd_info_t *rcvdInfo)
|
|
{
|
|
switch(rcvdInfo->packageID) {
|
|
case INFO_PKG_ID_GENERIC_RAW:
|
|
strlib_free(rcvdInfo->info.generic_raw.info_package);
|
|
strlib_free(rcvdInfo->info.generic_raw.content_type);
|
|
strlib_free(rcvdInfo->info.generic_raw.message_body);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void dump_msg(char * name, unsigned int *msg, int len, unsigned int cmd) {
|
|
int i,j;
|
|
CCAPP_DEBUG(DEB_F_PREFIX"\n%s %x %d cmd=%d\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, "dump_msg"), name, msg, len, cmd);
|
|
for ( j=0;j<10;j++) {
|
|
for(i=0;i<16;i++) {
|
|
CCAPP_DEBUG(DEB_F_PREFIX"%08X ", DEB_F_PREFIX_ARGS(SIP_CC_PROV, "dump_msg"), msg[i+j]);
|
|
if ( (i+j+1)*4 >= len ) return;
|
|
}
|
|
CCAPP_DEBUG(DEB_F_PREFIX"\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, "dump_msg"));
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* A ccapp task listener
|
|
*/
|
|
void ccp_handler(void* msg, int type) {
|
|
static const char fname[] = "ccp_handler";
|
|
sessionProvider_cmd_t *cmdMsg;
|
|
session_feature_t *featMsg;
|
|
session_update_t *sessUpd;
|
|
feature_update_t *featUpd;
|
|
session_mgmt_t *sessMgmt;
|
|
session_send_info_t *sendInfo;
|
|
session_rcvd_info_t *rcvdInfo;
|
|
session_id_t sess_id;
|
|
session_data_t *data;
|
|
int length;
|
|
|
|
CCAPP_DEBUG(DEB_F_PREFIX"Received Cmd %s\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname),
|
|
CCAPP_TASK_CMD_PRINT(type) );
|
|
|
|
|
|
switch (type) {
|
|
case CCAPP_SERVICE_CMD:
|
|
cmdMsg = (sessionProvider_cmd_t *) msg;
|
|
CCApp_processCmds (cmdMsg->cmd, cmdMsg->cmdData.ccData.reason,
|
|
cmdMsg->cmdData.ccData.reason_info);
|
|
break;
|
|
|
|
case CCAPP_INVOKEPROVIDER_FEATURE:
|
|
featMsg = (session_feature_t *) msg;
|
|
processProviderEvent(GET_LINEID(featMsg->session_id), featMsg->featureID,
|
|
featMsg->featData.ccData.state);
|
|
if (featMsg->featData.ccData.info != NULL) {
|
|
strlib_free(featMsg->featData.ccData.info);
|
|
}
|
|
if (featMsg->featData.ccData.info1 != NULL) {
|
|
strlib_free(featMsg->featData.ccData.info1);
|
|
}
|
|
break;
|
|
case CCAPP_INVOKE_FEATURE:
|
|
featMsg = (session_feature_t *) msg;
|
|
CCAPP_DEBUG(DEB_F_PREFIX"CCAPP_INVOKE_FEATURE:sid=%d, fid=%d, line=%d, cid=%d, info=%s info1=%s\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname),
|
|
featMsg->session_id,
|
|
featMsg->featureID,
|
|
GET_LINEID(featMsg->session_id),
|
|
GET_CALLID(featMsg->session_id),
|
|
((featMsg->featureID == CC_FEATURE_KEYPRESS) ? "..." : featMsg->featData.ccData.info),
|
|
((featMsg->featureID == CC_FEATURE_KEYPRESS) ? "..." : featMsg->featData.ccData.info1));
|
|
processSessionEvent(GET_LINEID(featMsg->session_id), GET_CALLID(featMsg->session_id),
|
|
featMsg->featureID, featMsg->featData.ccData.state,
|
|
featMsg->featData.ccData);
|
|
if (featMsg->featData.ccData.info != NULL) {
|
|
strlib_free(featMsg->featData.ccData.info);
|
|
}
|
|
if (featMsg->featData.ccData.info1 != NULL) {
|
|
strlib_free(featMsg->featData.ccData.info1);
|
|
}
|
|
break;
|
|
|
|
case CCAPP_CLOSE_SESSION:
|
|
sess_id = *(session_id_t*)msg;
|
|
cc_feature(CC_SRC_UI, GET_CALLID(sess_id),
|
|
GET_LINEID(sess_id), CC_FEATURE_END_CALL, NULL);
|
|
break;
|
|
|
|
case CCAPP_SESSION_UPDATE:
|
|
sessUpd = (session_update_t *) msg;
|
|
// Udpate the local cache
|
|
CCAPP_DEBUG(DEB_F_PREFIX"CCAPP_SESSION_UPDATE:type:%d.\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), GET_SESS_TYPE(sessUpd->sessionID));
|
|
// XXX Why do this when sessType is in session_update_t already?
|
|
if (GET_SESS_TYPE(sessUpd->sessionID) == SESSIONTYPE_CALLCONTROL) {
|
|
ccappUpdateSessionData(sessUpd);
|
|
}
|
|
else {
|
|
CCAPP_DEBUG(DEB_F_PREFIX"Unknown type:%d\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), sessUpd->sessType);
|
|
}
|
|
freeSessionData(sessUpd);
|
|
break;
|
|
|
|
case CCAPP_FEATURE_UPDATE:
|
|
|
|
featUpd = (feature_update_t *) msg;
|
|
// Update Registration state
|
|
if (featUpd->featureID == DEVICE_REG_STATE)
|
|
CCAPP_DEBUG(DEB_F_PREFIX"DEVICE_REG_STATE\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
|
|
|
if(featUpd->update.ccFeatUpd.data.line_info.info == CC_REGISTERED)
|
|
CCAPP_DEBUG(DEB_F_PREFIX"CC_REGISTERED\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
|
|
|
if(gCCApp.state == (int) CC_INSERVICE)
|
|
CCAPP_DEBUG(DEB_F_PREFIX"CC_INSERVICE\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
|
|
|
if ( featUpd->featureID == DEVICE_REG_STATE &&
|
|
featUpd->update.ccFeatUpd.data.line_info.info == CC_REGISTERED &&
|
|
gCCApp.state != (int) CC_INSERVICE )
|
|
{
|
|
cc_uint32_t major_ver=0, minor_ver=0,addtnl_ver=0;
|
|
char name[CC_MAX_LEN_REQ_SUPP_PARAM_CISCO_SISTAG]={0};
|
|
platGetSISProtocolVer( &major_ver, &minor_ver, &addtnl_ver, name);
|
|
CCAPP_DEBUG(DEB_F_PREFIX"The SIS verion is: %s, sis ver: %d.%d.%d \n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), name, major_ver, minor_ver, addtnl_ver);
|
|
if(!strncmp(name, REQ_SUPP_PARAM_CISCO_CME_SISTAG, strlen(REQ_SUPP_PARAM_CISCO_CME_SISTAG))){
|
|
CCAPP_DEBUG(DEB_F_PREFIX"This is CUCME mode.\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
|
} else if(!strncmp(name, REQ_SUPP_PARAM_CISCO_SISTAG, strlen(REQ_SUPP_PARAM_CISCO_SISTAG))){
|
|
CCAPP_DEBUG(DEB_F_PREFIX"This is CUCM mode.\n",DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
|
} else {
|
|
CCAPP_DEBUG(DEB_F_PREFIX"This is unknown mode.\n",DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
|
}
|
|
|
|
gCCApp.state = CC_INSERVICE;
|
|
gCCApp.cause = CC_CAUSE_NONE;
|
|
|
|
// Notify INS/OOS state to Session Manager if required
|
|
ccapp_hlapi_update_device_reg_state();
|
|
ccpro_handleINS();
|
|
|
|
if (gCCApp.cucm_mode == FAILOVER) {
|
|
cc_fail_fallback_sip(CC_SRC_UI, RSP_COMPLETE, CC_REG_FAILOVER_RSP, FALSE);
|
|
}
|
|
if (gCCApp.cucm_mode == FALLBACK) {
|
|
cc_fail_fallback_sip(CC_SRC_UI, RSP_COMPLETE, CC_REG_FALLBACK_RSP, FALSE);
|
|
}
|
|
gCCApp.cucm_mode = NONE_AVAIL;
|
|
}
|
|
|
|
ccappFeatureUpdated(featUpd);
|
|
break;
|
|
|
|
case CCAPP_SESSION_MGMT:
|
|
sessMgmt = (session_mgmt_t *) msg;
|
|
ccappSyncSessionMgmt(sessMgmt);
|
|
break;
|
|
|
|
case CCAPP_SEND_INFO:
|
|
sendInfo = (session_send_info_t *) msg;
|
|
data = (session_data_t *)findhash(sendInfo->sessionID);
|
|
|
|
if ( data != NULL && data->state == CONNECTED ) {
|
|
cc_int_info(CC_SRC_UI, CC_SRC_SIP,
|
|
GET_CALLID(sendInfo->sessionID),
|
|
GET_LINEID(sendInfo->sessionID),
|
|
sendInfo->generic_raw.info_package,
|
|
sendInfo->generic_raw.content_type,
|
|
sendInfo->generic_raw.message_body);
|
|
}
|
|
strlib_free(sendInfo->generic_raw.message_body);
|
|
strlib_free(sendInfo->generic_raw.content_type);
|
|
strlib_free(sendInfo->generic_raw.info_package);
|
|
break;
|
|
|
|
case CCAPP_RCVD_INFO:
|
|
sendInfo = (session_send_info_t *) msg;
|
|
data = (session_data_t *)findhash(sendInfo->sessionID);
|
|
rcvdInfo = (session_rcvd_info_t *) msg;
|
|
|
|
length = strlen((const char*)rcvdInfo->info.generic_raw.message_body);
|
|
if (data != NULL) {
|
|
CCAPP_DEBUG(DEB_F_PREFIX"rcvdInfo: addr=%x length=%d, xml=%s\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, "CCAPI-CONFPARSE"),
|
|
&data->call_conference, length, rcvdInfo->info.generic_raw.message_body);
|
|
|
|
data->info_package = rcvdInfo->info.generic_raw.info_package;
|
|
data->info_type = rcvdInfo->info.generic_raw.content_type;
|
|
data->info_body = rcvdInfo->info.generic_raw.message_body;
|
|
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_RECEIVED_INFO, CREATE_CALL_HANDLE_FROM_SESSION_ID(rcvdInfo->sessionID));
|
|
|
|
// most of the time isConference will be true at this point, we can notify the app of
|
|
// the updated participant info. However, if we're transitioning from non conference into
|
|
// conference, then we'll delay this notification until we're fully in conference state
|
|
if (CCAPI_CallInfo_getIsConference(data))
|
|
{ // in conference - send the info
|
|
ccsnap_gen_callEvent(CCAPI_CALL_EV_CONF_PARTICIPANT_INFO, CREATE_CALL_HANDLE_FROM_SESSION_ID(rcvdInfo->sessionID));
|
|
}
|
|
|
|
// one shot notify cleanup after event generation
|
|
data->info_package = strlib_empty();
|
|
data->info_type = strlib_empty();
|
|
data->info_body = strlib_empty();
|
|
}
|
|
freeRcvdInfo(rcvdInfo);
|
|
break;
|
|
|
|
case CCAPP_UPDATELINES:
|
|
notify_register_update(*(int *)msg);
|
|
break;
|
|
|
|
case CCAPP_MODE_NOTIFY:
|
|
case CCAPP_FAILOVER_IND:
|
|
case CCAPP_SHUTDOWN_ACK:
|
|
case CCAPP_FALLBACK_IND:
|
|
case CCAPP_REG_ALL_FAIL:
|
|
featUpd = (feature_update_t *) msg;
|
|
ccappHandleRegStateUpdates(featUpd);
|
|
break;
|
|
|
|
case CCAPP_THREAD_UNLOAD:
|
|
destroy_ccapp_thread();
|
|
break;
|
|
default:
|
|
APP_ERR_MSG("CCApp_Task: Error: Unknown message %d msg =0x%x\n", type, msg);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Function: destroy_ccapp_thread
|
|
* Description: shutdown and kill ccapp thread
|
|
* Parameters: none
|
|
* Returns: none
|
|
*/
|
|
void destroy_ccapp_thread()
|
|
{
|
|
static const char fname[] = "destroy_ccapp_thread";
|
|
TNP_DEBUG(DEB_F_PREFIX"Unloading ccapp and destroying ccapp thread\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_INIT, fname));
|
|
platform_initialized = FALSE;
|
|
CCAppShutdown();
|
|
(void)cprDestroyThread(ccapp_thread);
|
|
}
|
|
|
|
/**
|
|
* CCAPP wrapper to update device features.
|
|
* @param featUpd - feature_update_t
|
|
* @return void
|
|
*/
|
|
static
|
|
void ccappFeatureUpdated (feature_update_t *featUpd) {
|
|
cc_line_info_t *line_info;
|
|
|
|
switch(featUpd->featureID) {
|
|
case DEVICE_FEATURE_CFWD:
|
|
line_info = ccsnap_getLineInfoFromBtn(featUpd->update.ccFeatUpd.data.cfwd.line);
|
|
if ( line_info != NULL ) {
|
|
line_info->isCFWD = featUpd->update.ccFeatUpd.data.cfwd.isFwd;
|
|
line_info->isLocalCFWD = featUpd->update.ccFeatUpd.data.cfwd.isLocal;
|
|
line_info->cfwd_dest = strlib_update(line_info->cfwd_dest, featUpd->update.ccFeatUpd.data.cfwd.cfa_num);
|
|
ccsnap_gen_lineEvent(CCAPI_LINE_EV_CFWDALL, line_info->button);
|
|
}
|
|
CC_Config_setStringValue(CFGID_LINE_CFWDALL+featUpd->update.ccFeatUpd.data.cfwd.line-1, featUpd->update.ccFeatUpd.data.cfwd.cfa_num);
|
|
|
|
break;
|
|
case DEVICE_FEATURE_MWI:
|
|
line_info = ccsnap_getLineInfoFromBtn(featUpd->update.ccFeatUpd.data.mwi_status.line);
|
|
if ( line_info != NULL ) {
|
|
line_info->mwi.status = featUpd->update.ccFeatUpd.data.mwi_status.status;
|
|
line_info->mwi.type = featUpd->update.ccFeatUpd.data.mwi_status.type;
|
|
line_info->mwi.new_count = featUpd->update.ccFeatUpd.data.mwi_status.newCount;
|
|
line_info->mwi.old_count = featUpd->update.ccFeatUpd.data.mwi_status.oldCount;
|
|
line_info->mwi.pri_new_count = featUpd->update.ccFeatUpd.data.mwi_status.hpNewCount;
|
|
line_info->mwi.pri_old_count = featUpd->update.ccFeatUpd.data.mwi_status.hpOldCount;
|
|
ccsnap_gen_lineEvent(CCAPI_LINE_EV_MWI, line_info->button);
|
|
}
|
|
//Added for automation test
|
|
NOTIFY_LINE_DEBUG(DEB_NOTIFY_PREFIX"[line=%d][state=%s]",
|
|
"MWIChanged", featUpd->update.ccFeatUpd.data.mwi_status.line,
|
|
(featUpd->update.ccFeatUpd.data.mwi_status.status)?"ON":"OFF");
|
|
|
|
break;
|
|
case DEVICE_FEATURE_MWILAMP:
|
|
g_deviceInfo.mwi_lamp = featUpd->update.ccFeatUpd.data.state_data.state;
|
|
ccsnap_gen_deviceEvent(CCAPI_DEVICE_EV_MWI_LAMP, CC_DEVICE_ID);
|
|
break;
|
|
case DEVICE_FEATURE_BLF:
|
|
sub_hndlr_NotifyBLFStatus(featUpd->update.ccFeatUpd.data.blf_data.request_id,
|
|
featUpd->update.ccFeatUpd.data.blf_data.state,
|
|
featUpd->update.ccFeatUpd.data.blf_data.app_id);
|
|
break;
|
|
case DEVICE_FEATURE_MNC_REACHED:
|
|
line_info = ccsnap_getLineInfoFromBtn(featUpd->update.ccFeatUpd.data.line_info.line);
|
|
if ( line_info != NULL ) {
|
|
ccsnap_handle_mnc_reached(line_info,
|
|
featUpd->update.ccFeatUpd.data.line_info.info, gCCApp.mode);
|
|
ccsnap_gen_lineEvent(CCAPI_LINE_EV_CAPSET_CHANGED, line_info->button);
|
|
}
|
|
break;
|
|
case DEVICE_SERVICE_CONTROL_REQ:
|
|
reset_type = (cc_srv_ctrl_req_t) featUpd->update.ccFeatUpd.data.reset_type;
|
|
ccpro_handleserviceControlNotify();
|
|
break;
|
|
case DEVICE_NOTIFICATION:
|
|
g_deviceInfo.not_prompt = ccsnap_EscapeStrToLocaleStr(g_deviceInfo.not_prompt, featUpd->update.ccFeatUpd.data.notification.prompt, LEN_UNKNOWN);
|
|
g_deviceInfo.not_prompt_prio = featUpd->update.ccFeatUpd.data.notification.priority;
|
|
g_deviceInfo.not_prompt_prog = featUpd->update.ccFeatUpd.data.notification.notifyProgress;
|
|
ccsnap_gen_deviceEvent(CCAPI_DEVICE_EV_NOTIFYPROMPT, CC_DEVICE_ID);
|
|
break;
|
|
case DEVICE_LABEL_N_SPEED:
|
|
// todo
|
|
break;
|
|
case DEVICE_REG_STATE:
|
|
line_info = ccsnap_getLineInfoFromBtn(featUpd->update.ccFeatUpd.data.line_info.line);
|
|
if ( line_info != NULL ) {
|
|
line_info->reg_state = featUpd->update.ccFeatUpd.data.line_info.info;
|
|
ccsnap_gen_lineEvent(CCAPI_LINE_EV_REG_STATE, line_info->button);
|
|
}
|
|
break;
|
|
case DEVICE_CCM_CONN_STATUS:
|
|
ccsnap_update_ccm_status(featUpd->update.ccFeatUpd.data.ccm_conn.addr,
|
|
featUpd->update.ccFeatUpd.data.ccm_conn.status);
|
|
ccsnap_gen_deviceEvent(CCAPI_DEVICE_EV_SERVER_STATUS, CC_DEVICE_ID);
|
|
break;
|
|
default:
|
|
DEF_DEBUG(DEB_F_PREFIX"Unknown event: id= %d\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, "ccappFeatureUpdated"), featUpd->featureID);
|
|
break;
|
|
|
|
}
|
|
if ( featUpd->featureID == DEVICE_NOTIFICATION) {
|
|
strlib_free(featUpd->update.ccFeatUpd.data.notification.prompt);
|
|
}
|
|
|
|
if ( featUpd->featureID == DEVICE_CCM_CONN_STATUS) {
|
|
strlib_free(featUpd->update.ccFeatUpd.data.ccm_conn.addr);
|
|
}
|
|
|
|
if ( featUpd->featureID == DEVICE_FEATURE_CFWD) {
|
|
strlib_free(featUpd->update.ccFeatUpd.data.cfwd.cfa_num);
|
|
}
|
|
|
|
if (featUpd->featureID == DEVICE_SYNC_CONFIG_VERSION) {
|
|
strlib_free(featUpd->update.ccFeatUpd.data.cfg_ver_data.cfg_ver);
|
|
strlib_free(featUpd->update.ccFeatUpd.data.cfg_ver_data.dp_ver);
|
|
strlib_free(featUpd->update.ccFeatUpd.data.cfg_ver_data.softkey_ver);
|
|
}
|
|
|
|
if (featUpd->featureID == DEVICE_LABEL_N_SPEED) {
|
|
strlib_free(featUpd->update.ccFeatUpd.data.cfg_lbl_n_spd.speed);
|
|
strlib_free(featUpd->update.ccFeatUpd.data.cfg_lbl_n_spd.label);
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
*
|
|
* CCApp Provider wrapper for synchronous calls.
|
|
*
|
|
* @param sessMgmt - session management message
|
|
*
|
|
* @return void
|
|
*
|
|
* @pre None
|
|
*/
|
|
void ccappSyncSessionMgmt(session_mgmt_t *sessMgmt)
|
|
{
|
|
cc_line_info_t *line_info;
|
|
CCAPP_DEBUG(DEB_F_PREFIX"ccappSyncSessionMgmt: func_id=%d \n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, "ccappSyncSessionMgmt"),
|
|
sessMgmt->func_id);
|
|
|
|
//sessionMgmt(sessMgmt);
|
|
switch (sessMgmt->func_id) {
|
|
case SESSION_MGMT_SET_TIME:
|
|
g_deviceInfo.reg_time = sessMgmt->data.time.gmt_time;
|
|
CCAPP_DEBUG(DEB_F_PREFIX"Setting reg_time to == %lld\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV,
|
|
"ccappSyncSessionMgmt"), g_deviceInfo.reg_time);
|
|
platSetCucmRegTime();
|
|
break;
|
|
case SESSION_MGMT_GET_PHRASE_TEXT:
|
|
sessMgmt->data.phrase_text.ret_val =
|
|
platGetPhraseText(sessMgmt->data.phrase_text.ndx,
|
|
sessMgmt->data.phrase_text.outstr,
|
|
sessMgmt->data.phrase_text.len);
|
|
break;
|
|
case SESSION_MGMT_GET_UNREG_REASON:
|
|
sessMgmt->data.unreg_reason.unreg_reason = platGetUnregReason();
|
|
break;
|
|
case SESSION_MGMT_UPDATE_KPMLCONFIG:
|
|
platSetKPMLConfig(sessMgmt->data.kpmlconfig.kpml_val);
|
|
break;
|
|
case SESSION_MGMT_GET_AUDIO_DEVICE_STATUS:
|
|
//Noop
|
|
break;
|
|
case SESSION_MGMT_CHECK_SPEAKER_HEADSET_MODE:
|
|
//Noop
|
|
break;
|
|
case SESSION_MGMT_LINE_HAS_MWI_ACTIVE:
|
|
line_info = ccsnap_getLineInfoFromBtn(sessMgmt->data.line_mwi_active.line);
|
|
if (line_info != NULL) {
|
|
sessMgmt->data.line_mwi_active.ret_val = line_info->mwi.status;
|
|
}
|
|
break;
|
|
case SESSION_MGMT_APPLY_CONFIG:
|
|
// save the proposed versions of fcp and dialplan to apply. Will check against
|
|
// current versions and redownload if necessary
|
|
|
|
if (pending_action_type == NO_ACTION) {
|
|
configApplyConfigNotify(sessMgmt->data.config.config_version_stamp,
|
|
sessMgmt->data.config.dialplan_version_stamp,
|
|
sessMgmt->data.config.fcp_version_stamp,
|
|
sessMgmt->data.config.cucm_result,
|
|
sessMgmt->data.config.load_id,
|
|
sessMgmt->data.config.inactive_load_id,
|
|
sessMgmt->data.config.load_server,
|
|
sessMgmt->data.config.log_server,
|
|
sessMgmt->data.config.ppid);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
freeSessionMgmtData(sessMgmt);
|
|
|
|
}
|
|
|
|
/**
|
|
* ccCreateSession
|
|
*
|
|
* Called to create a CC session
|
|
*
|
|
* @param param - ccSession_create_param_t
|
|
* Contains the type of session and specific data
|
|
*
|
|
* @return ccSession_id_t - id of the session created
|
|
*/
|
|
session_id_t createSessionId(line_t line, callid_t call)
|
|
{
|
|
return ( SESSIONTYPE_CALLCONTROL << SID_TYPE_SHIFT ) +
|
|
(line << SID_LINE_SHIFT ) + call;
|
|
}
|
|
|
|
/**
|
|
* getLineIdAndCallId
|
|
*
|
|
* get Line and call_id
|
|
*
|
|
* @param *line_id
|
|
* @param *call_id
|
|
*
|
|
*/
|
|
void getLineIdAndCallId (line_t *line_id, callid_t *call_id)
|
|
{
|
|
// assign proper line_id and call_id if not already there
|
|
if ((*line_id) == 0 || (*line_id) == CC_ALL_LINES) {
|
|
/*
|
|
* If the filter is the All Calls Complex Filter and the primary line
|
|
* is at its configured call capacity, the next available line should
|
|
* be used. In this scenario, sessionUI/Mgr send the line_id as zero.
|
|
*/
|
|
(*line_id) = lsm_get_available_line(FALSE);
|
|
}
|
|
|
|
if ((*call_id) == 0) {
|
|
(*call_id) = cc_get_new_call_id();
|
|
}
|
|
}
|