Exemplo n.º 1
0
/*
 *  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;
}
Exemplo n.º 2
0
/*
 *  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;
}
Exemplo n.º 3
0
/*
 *  Function: get_state()
 *
 *  Parameters: request_id - unique id assigned by the platform to this subscription. Platform
 *                           uses this to track the status updates and to make subsequent termination
 *                           request.
 *              duration - how long the subscription is requested to be valid.
 *              watcher - entity that is requesting the presence state.
 *              presentity - entity whose presence state is requested.
 *              app_id - application that is making the subscription.
 *                       0: indicates call list blf application.
 *                       1..n: indicates the speeddial/blf associated with (1..n)th line button.
 *              feature_mask - indicates the additional features enabled.
 *
 *  Description:  is invoked by platform side whenever it needs to susbcribe
 *                for presence state of a presentity. This stores the susbcription
 *                data in a linked list and posts SIPSPI_EV_CC_SUBSCRIBE
 *                to SIP stack. We need to store the subscription data so that
 *                SUBSCRIBE response and NOTIFYs can be mapped to subscriptions.
 *
 *  Returns: void
 */
static void
get_state (int request_id,
           int duration,
           const char *watcher,
           const char *presentity,
           int app_id,
           int feature_mask)
{
    static const char fname[] = "get_state";
    pres_subscription_req_t *sub_req_p;

    DEF_DEBUG(DEB_F_PREFIX"REQ %d: TM %d: WTR %s: PRT %s: FMSK %d: APP %d",
         DEB_F_PREFIX_ARGS(BLF_INFO, fname),
         request_id, duration, watcher, presentity, feature_mask, app_id);
    /*
     * if there is no subscription list yet, create one.
     */
    if (s_pres_req_list == NULL) {
        s_pres_req_list = sll_create(find_matching_node);
        if (s_pres_req_list == NULL) {
            /* let platform know that we can not continue */
            ui_BLF_notification(request_id, CC_SIP_BLF_REJECTED, app_id);
            BLF_ERROR(MISC_F_PREFIX"Exiting : request list creation failed", fname);
            return;
        }
    }
    /*
     * check if a request is already created by walking through the list. if not, create one.
     */
    if ((sub_req_p = (pres_subscription_req_t *)
                sll_find(s_pres_req_list, &request_id)) == NULL) {
        /*
         * populate subscription request and append it to the list.
         */
        sub_req_p = (pres_subscription_req_t *)
            cpr_malloc(sizeof(pres_subscription_req_t));
        if (sub_req_p == NULL) {
            BLF_ERROR(MISC_F_PREFIX"Exiting : malloc failed", fname);
            return;
        }

        sub_req_p->request_id = request_id;
        sub_req_p->sub_id = CCSIP_SUBS_INVALID_SUB_ID;
        sub_req_p->highest_cseq = 0;
        sub_req_p->duration = duration;
        sstrncpy(sub_req_p->presentity, presentity, CC_MAX_DIALSTRING_LEN);
        sstrncpy(sub_req_p->watcher, watcher, CC_MAX_DIALSTRING_LEN);
        sub_req_p->app_id = app_id;
        sub_req_p->feature_mask = feature_mask;
        sub_req_p->blf_state = CC_SIP_BLF_UNKNOWN;

        (void) sll_append(s_pres_req_list, sub_req_p);
    } else { /* already exists. just update the duration */
        sub_req_p->duration = duration;
    }

    /*
     * post SIPSPI_EV_CC_SUBSCRIBE to SIP stack
     */
    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);
        /* let platform know that we can not continue */
        ui_BLF_notification(request_id, CC_SIP_BLF_REJECTED, app_id);
        BLF_ERROR(MISC_F_PREFIX"Exiting : Unable to send SUBSCRIBE", fname);
        return;
    }

    BLF_DEBUG(DEB_F_PREFIX"Exiting : request made successfully", DEB_F_PREFIX_ARGS(BLF, fname));
    return;
}
Exemplo n.º 4
0
/*
 *  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)\n",
              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\n", 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\n", 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\n", 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\n",
                                  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\n", fname);
                }
                BLF_DEBUG(DEB_F_PREFIX"subscribed again after expiration\n", 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\n",
            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\n", DEB_F_PREFIX_ARGS(BLF, fname));
    return;
}