/* * Function: terminate_req_all() * * Parameters: none. * * Description: terminates all out standing subscriptions * * Returns: void */ static void terminate_req_all (void) { static const char fname[] = "terminate_req_all"; pres_subscription_req_t *sub_req_p; BLF_DEBUG(DEB_F_PREFIX"Entering", DEB_F_PREFIX_ARGS(BLF, fname)); if (s_pres_req_list == NULL) { BLF_DEBUG(DEB_F_PREFIX"Exiting : no outstanding requests", DEB_F_PREFIX_ARGS(BLF, fname)); return; } while ((sub_req_p = (pres_subscription_req_t *) sll_next(s_pres_req_list, NULL)) != NULL) { /* * post SIPSPI_EV_CC_SUBSCRIPTION_TERMINATED so that SIP stack cleans up. */ (void) sub_int_subscribe_term(sub_req_p->sub_id, TRUE, sub_req_p->request_id, CC_SUBSCRIPTIONS_PRESENCE); /* * and remove the node from the list of subscriptions. */ free_sub_request(sub_req_p); } /* * this function call indicates the subscription handler is going * out of service, set s_subs_hndlr_initialized to FALSE. */ s_subs_hndlr_initialized = FALSE; BLF_DEBUG(DEB_F_PREFIX"Exiting", DEB_F_PREFIX_ARGS(BLF, fname)); }
/** * This function will process SUBSCRIBED feature NOTIFY messages. * * @param[in] msg - pointer to ccsip_sub_not_data_t * * @return none * * @pre (msg != NULL) */ static void sub_process_feature_notify (ccsip_sub_not_data_t *msg, callid_t call_id, callid_t other_call_id) { static const char fname[] = "sub_process_feature_notify"; ccsip_event_data_t *ev_data; cc_feature_ack_t temp_msg; /* * send response to NOTIFY. */ (void)sub_int_notify_ack(msg->sub_id, SIP_STATUS_SUCCESS, msg->u.notify_ind_data.cseq); /* * if the subscription state is terminated, clean up the subscription. */ if (msg->u.notify_ind_data.subscription_state == SUBSCRIPTION_STATE_TERMINATED) { /* * post SIPSPI_EV_CC_SUBSCRIPTION_TERMINATED. * do not force SUB/NOT mgr to cleanup SCB immediately, because we may have to handle digest * challenges to terminating SUBSCRIBE sent. */ (void)sub_int_subscribe_term(msg->sub_id, FALSE, msg->request_id, CC_SUBSCRIPTIONS_REMOTECC); } ev_data = msg->u.notify_ind_data.eventData; msg->u.notify_ind_data.eventData = NULL; if (ev_data == NULL) { GSM_ERR_MSG(DEB_F_PREFIX"No body in the NOTIFY message\n", DEB_F_PREFIX_ARGS(GSM, fname)); /* * if (no content & subscription state is TERMINATED * then reset active_feature to NONE. */ if (msg->u.notify_ind_data.subscription_state == SUBSCRIPTION_STATE_TERMINATED) { memset(&temp_msg, 0, sizeof(temp_msg)); temp_msg.msg_id = CC_MSG_FEATURE_ACK; temp_msg.src_id = CC_SRC_GSM; temp_msg.call_id = call_id; fim_process_event((void *)&temp_msg, FALSE); } return; } // other types of event data is not supported as of now. free_event_data(ev_data); }
/* * Function: terminate_req() * * Parameters: request_id - unique id of the subscription which needs to be terminated. * * Description: is invoked by platform to terminate a subscription. * First, it posts SIPSPI_EV_CC_SUBSCRIBE to SIP stack with duration = 0. * and then, it posts SIPSPI_EV_CC_SUBSCRIPTION_TERMINATED to SIP stack. * * Returns: void */ static void terminate_req (int request_id) { static const char fname[] = "terminate_req"; pres_subscription_req_t *sub_req_p; BLF_DEBUG(DEB_F_PREFIX"Entering (request_id=%d)", DEB_F_PREFIX_ARGS(BLF, fname), request_id); /* * check if the request exists. */ if ((sub_req_p = (pres_subscription_req_t *) sll_find(s_pres_req_list, &request_id)) == NULL) { BLF_ERROR(MISC_F_PREFIX"request does not exist in the list", fname); return; } /* * post SIPSPI_EV_CC_SUBSCRIBE to SIP stack with duration = 0 */ sub_req_p->duration = 0; /* * no point in checking return value of the subsmanager_handle_ev_app_subscribe() * because we are terminating the request anyway. */ (void) send_subscribe_ev_to_sip_task(sub_req_p); /* * post SIPSPI_EV_CC_SUBSCRIPTION_TERMINATED. * do not force SUB/NOT mgr to cleanup SCB immediately, because we may have to handle digest * challenges to terminating SUBSCRIBE sent. */ (void) sub_int_subscribe_term(sub_req_p->sub_id, FALSE, sub_req_p->request_id, CC_SUBSCRIPTIONS_PRESENCE); /* * and remove the node from the list of subscriptions. */ free_sub_request(sub_req_p); BLF_DEBUG(DEB_F_PREFIX"Exiting : request terminated", DEB_F_PREFIX_ARGS(BLF, fname)); return; }
void configapp_process_request (ccsip_sub_not_data_t *msg) { static const char fname[] = "configapp_process_request"; ConfigApp_req_data_t *configdata; configdata = &(msg->u.subs_ind_data.eventData->u.configapp_data); update_kpmlconfig(configdata->sip_profile.kpml_val); CONFIGAPP_DEBUG(DEB_F_PREFIX"Updated kpml config value to %d.", DEB_F_PREFIX_ARGS(CONFIG_APP, fname), configdata->sip_profile.kpml_val); (void)sub_int_subscribe_ack(CC_SRC_MISC_APP, CC_SRC_SIP, msg->sub_id, (uint16_t)SIP_SUCCESS_SETUP, 0); (void)sub_int_subscribe_term(msg->sub_id, TRUE, 0, CC_SUBSCRIPTIONS_CONFIGAPP); configapp_free_event_data(msg->u.subs_ind_data.eventData); return; }
/* * Function: notify_ind_cb() * * Parameters: msg_data - the response data provoded by SIP stack. * * Description: is invoked by SIP stack when it receives a NOTIFY message. it takes * action based on subscription_state and blf state derived from event body. * * Returns: void */ static void notify_ind_cb (ccsip_sub_not_data_t * msg_data) { static const char fname[] = "notify_ind_cb"; int sub_state = msg_data->u.notify_ind_data.subscription_state; sip_subs_state_reason_e reason = msg_data->u.notify_ind_data.subscription_state_reason; uint32_t retry_after = msg_data->u.notify_ind_data.retry_after; int request_id = msg_data->request_id; sub_id_t sub_id = msg_data->sub_id; pres_subscription_req_t *sub_req_p; Presence_ext_t *event_body_p = NULL; uint32_t cseq = msg_data->u.notify_ind_data.cseq; int blf_state; BLF_DEBUG(DEB_F_PREFIX"Entering (subscription_state=%d)", DEB_F_PREFIX_ARGS(BLF, fname), sub_state); /* * memory for event bodies is allocated by sip stack and it is the * responsibility of the user (this module) to free it when it is done with it. */ if ((msg_data->u.notify_ind_data.eventData != NULL) && (msg_data->u.notify_ind_data.eventData->type != EVENT_DATA_PRESENCE)) { BLF_ERROR(MISC_F_PREFIX"NOTIFY does not contain presence body", fname); free_event_data(msg_data->u.notify_ind_data.eventData); msg_data->u.notify_ind_data.eventData = NULL; } event_body_p = (msg_data->u.notify_ind_data.eventData == NULL) ? NULL : &(msg_data->u.notify_ind_data.eventData->u.presence_rpid); if ((s_pres_req_list == NULL) || ((sub_req_p = (pres_subscription_req_t *) sll_find(s_pres_req_list, &request_id)) == NULL)) { /* * since we do not have subscription for this, help SIP stack clean up. * first, post SIPSPI_EV_CC_NOTIFY_RESPONSE so that SIP stack sends 481, then * post SIPSPI_EV_CC_SUBSCRIPTION_TERMINATED so that SIP stack cleans up. */ (void) sub_int_notify_ack(sub_id, SIP_CLI_ERR_CALLEG, cseq); (void) sub_int_subscribe_term(sub_id, TRUE, request_id, CC_SUBSCRIPTIONS_PRESENCE); free_event_data(msg_data->u.notify_ind_data.eventData); BLF_DEBUG(DEB_F_PREFIX"Exiting : subscription does not exist", DEB_F_PREFIX_ARGS(BLF, fname)); return; } /* * post SIPSPI_EV_CC_NOTIFY_RESPONSE. */ (void) sub_int_notify_ack(sub_id, SIP_STATUS_SUCCESS, cseq); /* * check if it is out of sequence NOTIFY, if so, do not use the presence state carried in it. */ if (cseq < sub_req_p->highest_cseq) { free_event_data(msg_data->u.notify_ind_data.eventData); BLF_ERROR(MISC_F_PREFIX"Exiting : out of sequence NOTIFY received", fname); return; } else { sub_req_p->highest_cseq = cseq; } /* * If the Subscription_state is terminated, then ... */ if (sub_state == SUBSCRIPTION_STATE_TERMINATED) { /* * post SIPSPI_EV_CC_SUBSCRIPTION_TERMINATED to SIP stack. */ (void) sub_int_subscribe_term(sub_id, TRUE, sub_req_p->request_id, CC_SUBSCRIPTIONS_PRESENCE); if (reason == SUBSCRIPTION_STATE_REASON_DEACTIVATED) { /* if the reason is "decativated", re-subscribe. */ sub_req_p->sub_id = CCSIP_SUBS_INVALID_SUB_ID; sub_req_p->highest_cseq = 0; /* * post SIPSPI_EV_CC_SUBSCRIBE to SIP stack */ if (send_subscribe_ev_to_sip_task(sub_req_p) != CC_RC_SUCCESS) { /* let platform know that we can not continue */ ui_BLF_notification(request_id, CC_SIP_BLF_REJECTED, sub_req_p->app_id); /* * remove the node from the list of subscriptions. */ free_sub_request(sub_req_p); } } else if ((reason == SUBSCRIPTION_STATE_REASON_TIMEOUT) || (reason == SUBSCRIPTION_STATE_REASON_PROBATION) || (reason == SUBSCRIPTION_STATE_REASON_GIVEUP)) { /* let the app know that susbcription expired so that it can resusbcribe later */ ui_BLF_notification(request_id, CC_SIP_BLF_EXPIRED, sub_req_p->app_id); sub_req_p->blf_state = CC_SIP_BLF_EXPIRED; if (sub_req_p->app_id > 0) { /* * Since it is speeddial/blf, we must send a new subscription. */ sub_req_p->sub_id = CCSIP_SUBS_INVALID_SUB_ID; sub_req_p->highest_cseq = 0; if ((reason == SUBSCRIPTION_STATE_REASON_PROBATION) || (reason == SUBSCRIPTION_STATE_REASON_GIVEUP)) { /* * Start a timer based on retry-after value. If retry-after value is 0, * use a default value of 5 sec */ if (retry_after == 0) { retry_after = DEFAULT_RETRY_AFTER_MILLISECS; } else { retry_after = (retry_after * 1000); // converting into millisecs } if ((cprCancelTimer(s_retry_after_timers[sub_req_p->app_id - 1]) == CPR_SUCCESS) && (cprStartTimer(s_retry_after_timers[sub_req_p->app_id - 1], retry_after, (void *) sub_req_p) == CPR_SUCCESS)) { /* * Timer successfully started. free up event data and return. */ free_event_data(msg_data->u.notify_ind_data.eventData); BLF_DEBUG(DEB_F_PREFIX"Exiting : retry_after Timer started", DEB_F_PREFIX_ARGS(BLF, fname)); return; } } if (send_subscribe_ev_to_sip_task(sub_req_p) != CC_RC_SUCCESS) { /* * remove the node from the list of subscriptions. */ free_sub_request(sub_req_p); BLF_ERROR(MISC_F_PREFIX"Unable to send SUBSCRIBE", fname); } BLF_DEBUG(DEB_F_PREFIX"subscribed again after expiration", DEB_F_PREFIX_ARGS(BLF, fname)); } else { /* * and remove the node from the list of subscriptions. */ free_sub_request(sub_req_p); } } else { ui_BLF_notification(request_id, CC_SIP_BLF_REJECTED, sub_req_p->app_id); /* * and remove the node from the list of subscriptions. */ free_sub_request(sub_req_p); } } else { /* derive the BLF state from event data */ blf_state = extract_blf_state(event_body_p, sub_req_p->feature_mask); ui_BLF_notification(request_id, blf_state, sub_req_p->app_id); sub_req_p->blf_state = blf_state; /* * if blf state is ALERTING, * play blf alerting audible tone. */ if (blf_state == CC_SIP_BLF_ALERTING) { /* * Post an event to GSM to play alerting tone. */ cc_feature(CC_SRC_MISC_APP, CC_NO_CALL_ID, 0, CC_FEATURE_BLF_ALERT_TONE, NULL); } DEF_DEBUG(DEB_F_PREFIX"SUB %d: BLF %d", DEB_F_PREFIX_ARGS(BLF_INFO, fname), sub_state, blf_state); } free_event_data(msg_data->u.notify_ind_data.eventData); BLF_DEBUG(DEB_F_PREFIX"Exiting : acted based on subscription state", DEB_F_PREFIX_ARGS(BLF, fname)); return; }
/* * Function: subscribe_response_ind() * * Parameters: msg_data - the response data provoded by SIP stack. * * Description: is invoked by SIP stack when it receives a response message for * the SUBSCRIBE it sent out. For most of non-2xx final responses, * it posts SIPSPI_EV_CC_SUBSCRIPTION_TERMINATED to SIP stack and * lets the platform know that the subscription is rejected. * if the resp is 423 (interval too short), then resends the subscription * with double the previous duaration. * * Returns: void */ static void subscribe_response_ind (ccsip_sub_not_data_t *msg_data) { static const char fname[] = "subscribe_response_ind"; int status_code = msg_data->u.subs_result_data.status_code; int request_id = msg_data->request_id; sub_id_t sub_id = msg_data->sub_id; pres_subscription_req_t *sub_req_p; BLF_DEBUG(DEB_F_PREFIX"Entering (status_code=%d)", DEB_F_PREFIX_ARGS(BLF, fname), status_code); if ((s_pres_req_list == NULL) || ((sub_req_p = (pres_subscription_req_t *) sll_find(s_pres_req_list, &request_id)) == NULL)) { /* * since we do not have subscription for this, help SIP stack clean up. * post SIPSPI_EV_CC_SUBSCRIPTION_TERMINATED so that SIP stack cleans up. */ (void) sub_int_subscribe_term(sub_id, TRUE, request_id, CC_SUBSCRIPTIONS_PRESENCE); BLF_DEBUG(DEB_F_PREFIX"Exiting : subscription does not exist", DEB_F_PREFIX_ARGS(BLF, fname)); return; } /* * note sub_id so that sub_id will be used in the subsequent interaction with SIP stack */ sub_req_p->sub_id = sub_id; /* * If the status_code is 1xx or 2xx, then do nothing. */ if ((status_code >= 100) && (status_code < 300)) { /* do nothing */ BLF_DEBUG(DEB_F_PREFIX"Exiting :100-299 response", DEB_F_PREFIX_ARGS(BLF, fname)); return; } /* * If the status_code is 423 (interval too short), resend with the new duration. */ if (status_code == SIP_CLI_ERR_INTERVAL_TOO_SMALL) { sub_req_p->duration = msg_data->u.subs_result_data.expires; if (send_subscribe_ev_to_sip_task(sub_req_p) != CC_RC_SUCCESS) { /* let platform know that we can not continue */ ui_BLF_notification(request_id, CC_SIP_BLF_REJECTED, sub_req_p->app_id); /* * remove the node from the list of subscriptions. */ free_sub_request(sub_req_p); BLF_ERROR(MISC_F_PREFIX"Exiting : Unable to send SUBSCRIBE", fname); return; } BLF_DEBUG(DEB_F_PREFIX"Exiting : subscribed again with double duration", DEB_F_PREFIX_ARGS(BLF, fname)); return; } /* * if the status_code is 481 (sub does not exist) and the app_id is non-zero (sppeddial/blf), * terminate the existing one and send a new subscription. */ if ((status_code == SIP_CLI_ERR_CALLEG) && (sub_req_p->app_id > 0)) { ui_BLF_notification(request_id, CC_SIP_BLF_UNKNOWN, sub_req_p->app_id); /* until we get the current status */ sub_req_p->blf_state = CC_SIP_BLF_UNKNOWN; /* * post SIPSPI_EV_CC_SUBSCRIPTION_TERMINATED so that SIP stack cleans up. */ (void) sub_int_subscribe_term(sub_req_p->sub_id, TRUE, sub_req_p->request_id, CC_SUBSCRIPTIONS_PRESENCE); /* * send a new subscription */ sub_req_p->sub_id = CCSIP_SUBS_INVALID_SUB_ID; sub_req_p->highest_cseq = 0; if (send_subscribe_ev_to_sip_task(sub_req_p) != CC_RC_SUCCESS) { /* let platform know that we can not continue */ ui_BLF_notification(request_id, CC_SIP_BLF_REJECTED, sub_req_p->app_id); /* * remove the node from the list of subscriptions. */ free_sub_request(sub_req_p); BLF_ERROR(MISC_F_PREFIX"Exiting : Unable to send SUBSCRIBE", fname); return; } BLF_DEBUG(DEB_F_PREFIX"Exiting : subscribed again after receiving 481", DEB_F_PREFIX_ARGS(BLF, fname)); return; } /* * If the status_code is 481 (sub does not exist) and app_id is zero, terminate the subscription * so that platform can make a new subscription. * if the status_code is 403/603(forbidden), 489(Bad event), 401(Unauthorized) or * any uninterested code, then update the presence/BLF state as REJECTED. */ ui_BLF_notification(request_id, CC_SIP_BLF_REJECTED, sub_req_p->app_id); /* * post SIPSPI_EV_CC_SUBSCRIPTION_TERMINATED so that SIP stack cleans up. */ (void) sub_int_subscribe_term(sub_req_p->sub_id, TRUE, sub_req_p->request_id, CC_SUBSCRIPTIONS_PRESENCE); /* * and remove the node from the list of subscriptions. */ free_sub_request(sub_req_p); BLF_DEBUG(DEB_F_PREFIX"Exiting : request terminated", DEB_F_PREFIX_ARGS(BLF, fname)); return; }
/* * Function: terminate_cb() * * Parameters: msg_data - the response data provoded by SIP stack. * * Description: is invoked by SIP stack when it needs to terminate a subscription because of * some reason (failover, shutdown, etc). if the reason is shutdown, rollover, etc, * we will terminate the subscription. Platform will resubscribe later if it is a failover/fallback. * if it is a protocol error such as wrong header/wrong body, then terminate the subscription * and resubscribe immediately. * * Returns: void */ static void terminate_cb (ccsip_sub_not_data_t *msg_data) { static const char fname[] = "terminate_cb"; ccsip_reason_code_e reason_code = msg_data->reason_code; int status_code = msg_data->u.subs_term_data.status_code; int request_id = msg_data->request_id; sub_id_t sub_id = msg_data->sub_id; pres_subscription_req_t *sub_req_p = NULL; int orig_duration = 0; BLF_DEBUG(DEB_F_PREFIX"Entering (reason_code=%d, status_code=%d)", DEB_F_PREFIX_ARGS(BLF, fname), reason_code, status_code); if (s_pres_req_list != NULL) { sub_req_p = (pres_subscription_req_t *) sll_find(s_pres_req_list, &request_id); } if (sub_req_p == NULL) { /* * we are not aware of any such subcription. So * post SIPSPI_EV_CC_SUBSCRIPTION_TERMINATED so that SIP stack cleans up. */ (void) sub_int_subscribe_term(sub_id, TRUE, request_id, CC_SUBSCRIPTIONS_PRESENCE); BLF_DEBUG(DEB_F_PREFIX"Exiting : subscription does not exist", DEB_F_PREFIX_ARGS(BLF, fname)); return; } orig_duration = sub_req_p->duration; if (reason_code == SM_REASON_CODE_ERROR) { // protocol error /* * Send a terminating SUBSCRIBE (expires=0) to make sure other end terminates the subscription */ sub_req_p->duration = 0; /* * no point in checking return value of the subsmanager_handle_ev_app_subscribe() * because we are terminating the subscription anyway. */ (void) send_subscribe_ev_to_sip_task(sub_req_p); } /* * post SIPSPI_EV_CC_SUBSCRIPTION_TERMINATED so that SIP stack cleans up. * In case of SM_REASON_CODE_RESET_REG, SM_REASON_CODE_ROLLOVER & SM_REASON_CODE_SHUTDOWN, * SIP stack already cleaned up SCB. */ if ((reason_code != SM_REASON_CODE_RESET_REG) && (reason_code != SM_REASON_CODE_ROLLOVER) && (reason_code != SM_REASON_CODE_SHUTDOWN)) { (void) sub_int_subscribe_term(sub_id, TRUE, request_id, CC_SUBSCRIPTIONS_PRESENCE); } /* let platform know that the current state is UNKNOWN */ ui_BLF_notification(request_id, CC_SIP_BLF_UNKNOWN, sub_req_p->app_id); if ((reason_code == SM_REASON_CODE_ERROR) || (reason_code == SM_REASON_CODE_RESET_REG)) { /* * send a new subscription */ sub_req_p->sub_id = CCSIP_SUBS_INVALID_SUB_ID; sub_req_p->highest_cseq = 0; sub_req_p->duration = orig_duration; (void) send_subscribe_ev_to_sip_task(sub_req_p); } else { /* * remove the node from the list of subscriptions because we may be shutting down/rolling over. */ free_sub_request(sub_req_p); } BLF_DEBUG(DEB_F_PREFIX"Exiting : terminated subscription", DEB_F_PREFIX_ARGS(BLF, fname)); return; }