コード例 #1
0
ファイル: sip_timer.c プロジェクト: Archipov/android-client
/* Timer callback. When the timer is fired, it can be time to refresh
 * the session if UA is the refresher, otherwise it is time to end 
 * the session.
 */
static void timer_cb(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
{
    pjsip_inv_session *inv = (pjsip_inv_session*) entry->user_data;
    pjsip_tx_data *tdata = NULL;
    pj_status_t status;
    pj_bool_t as_refresher;

    pj_assert(inv);

    PJ_UNUSED_ARG(timer_heap);

    /* Lock dialog. */
    pjsip_dlg_inc_lock(inv->dlg);

    /* Check our role */
    as_refresher =
	(inv->timer->refresher == TR_UAC && inv->timer->role == PJSIP_ROLE_UAC) ||
	(inv->timer->refresher == TR_UAS && inv->timer->role == PJSIP_ROLE_UAS);    

    /* Do action based on role(refresher or refreshee). 
     * As refresher:
     * - send refresh, or  
     * - end session if there is no response to the refresh request.
     * As refreshee:
     * - end session if there is no refresh request received.
     */
    if (as_refresher && (entry->id != REFRESHER_EXPIRE_TIMER_ID)) {
	pj_time_val now;

	/* As refresher, reshedule the refresh request on the following:
	 *  - must not send re-INVITE if another INVITE or SDP negotiation
	 *    is in progress.
	 *  - must not send UPDATE with SDP if SDP negotiation is in progress
	 */
	pjmedia_sdp_neg_state neg_state = pjmedia_sdp_neg_get_state(inv->neg);

	inv->timer->timer.id = 0;

	if ( (!inv->timer->use_update && (
			inv->invite_tsx != NULL ||
			neg_state != PJMEDIA_SDP_NEG_STATE_DONE)
             )
	     ||
	     (inv->timer->use_update && inv->timer->with_sdp &&
		     neg_state != PJMEDIA_SDP_NEG_STATE_DONE
	     )
	   )
	{
	    pj_time_val delay = {1, 0};

	    inv->timer->timer.id = 1;
	    pjsip_endpt_schedule_timer(inv->dlg->endpt, &inv->timer->timer,
				       &delay);
	    pjsip_dlg_dec_lock(inv->dlg);
	    return;
	}

	/* Refresher, refresh the session */
	if (inv->timer->use_update) {
	    const pjmedia_sdp_session *offer = NULL;

	    if (inv->timer->with_sdp) {
		pjmedia_sdp_neg_get_active_local(inv->neg, &offer);
	    }
	    status = pjsip_inv_update(inv, NULL, offer, &tdata);
	} else {
	    /* Create re-INVITE without modifying session */
	    pjsip_msg_body *body;
	    const pjmedia_sdp_session *offer = NULL;

	    pj_assert(pjmedia_sdp_neg_get_state(inv->neg) == 
		      PJMEDIA_SDP_NEG_STATE_DONE);

	    status = pjsip_inv_invite(inv, &tdata);
	    if (status == PJ_SUCCESS)
		status = pjmedia_sdp_neg_send_local_offer(inv->pool_prov, 
							  inv->neg, &offer);
	    if (status == PJ_SUCCESS)
		status = pjmedia_sdp_neg_get_neg_local(inv->neg, &offer);
	    if (status == PJ_SUCCESS) {
		status = pjsip_create_sdp_body(tdata->pool, 
					(pjmedia_sdp_session*)offer, &body);
		tdata->msg->body = body;
	    }
	}

	pj_gettimeofday(&now);
	PJ_LOG(4, (inv->pool->obj_name,
		   "Refreshing session after %ds (expiration period=%ds)",
		   (now.sec-inv->timer->last_refresh.sec),
		   inv->timer->setting.sess_expires));
    } else {
	
	pj_time_val now;

	if (as_refresher)
	    inv->timer->expire_timer.id = 0;
	else
	    inv->timer->timer.id = 0;

	/* Terminate the session */
	status = pjsip_inv_end_session(inv, PJSIP_SC_REQUEST_TIMEOUT, 
				       NULL, &tdata);

	pj_gettimeofday(&now);
	PJ_LOG(3, (inv->pool->obj_name, 
		   "No session %s received after %ds "
		   "(expiration period=%ds), stopping session now!",
		   (as_refresher?"refresh response":"refresh"),
		   (now.sec-inv->timer->last_refresh.sec),
		   inv->timer->setting.sess_expires));

    }

    /* Unlock dialog. */
    pjsip_dlg_dec_lock(inv->dlg);

    /* Send message, if any */
    if (tdata && status == PJ_SUCCESS) {
	inv->timer->refresh_tdata = tdata;

	status = pjsip_inv_send_msg(inv, tdata);	
    }

    /* Print error message, if any */
    if (status != PJ_SUCCESS) {
	PJ_PERROR(2, (inv->pool->obj_name, status,
		     "Error in %s session timer",
		     ((as_refresher && entry->id != REFRESHER_EXPIRE_TIMER_ID)? 
		       "refreshing" : "terminating")));
    }
}
コード例 #2
0
ファイル: sip_timer.c プロジェクト: max3903/SFLphone
/* Timer callback. When the timer is fired, it can be time to refresh
 * the session if UA is the refresher, otherwise it is time to end 
 * the session.
 */
void timer_cb(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
{
    pjsip_inv_session *inv = (pjsip_inv_session*) entry->user_data;
    pjsip_tx_data *tdata = NULL;
    pj_status_t status;
    pj_bool_t as_refresher;

    pj_assert(inv);

    PJ_UNUSED_ARG(timer_heap);

    /* When there is a pending INVITE transaction, delay/reschedule this timer
     * for five seconds to cover the case that pending INVITE fails and the
     * previous session is still active. If the pending INVITE is successful, 
     * timer state will be updated, i.e: restarted or stopped.
     */
    if (inv->invite_tsx != NULL) {
	pj_time_val delay = {5};

	inv->timer->timer.id = 1;
	pjsip_endpt_schedule_timer(inv->dlg->endpt, &inv->timer->timer, &delay);
	return;
    }

    /* Lock dialog. */
    pjsip_dlg_inc_lock(inv->dlg);

    /* Check our role */
    as_refresher = 
	(inv->timer->refresher == TR_UAC && inv->timer->role == PJSIP_ROLE_UAC) ||
	(inv->timer->refresher == TR_UAS && inv->timer->role == PJSIP_ROLE_UAS);

    /* Do action based on role, refresher or refreshee */
    if (as_refresher) {

	pj_time_val now;

	/* Refresher, refresh the session */
	if (inv->timer->use_update) {
	    /* Create UPDATE request without offer */
	    status = pjsip_inv_update(inv, NULL, NULL, &tdata);
	} else {
	    /* Create re-INVITE without modifying session */
	    pjsip_msg_body *body;
	    const pjmedia_sdp_session *offer = NULL;

	    pj_assert(pjmedia_sdp_neg_get_state(inv->neg) == 
		      PJMEDIA_SDP_NEG_STATE_DONE);

	    status = pjsip_inv_invite(inv, &tdata);
	    if (status == PJ_SUCCESS)
		status = pjmedia_sdp_neg_send_local_offer(inv->pool_prov, 
							  inv->neg, &offer);
	    if (status == PJ_SUCCESS)
		status = pjmedia_sdp_neg_get_neg_local(inv->neg, &offer);
	    if (status == PJ_SUCCESS) {
		status = pjsip_create_sdp_body(tdata->pool, 
					(pjmedia_sdp_session*)offer, &body);
		tdata->msg->body = body;
	    }
	}

	pj_gettimeofday(&now);
	PJ_LOG(4, (inv->pool->obj_name, 
		   "Refresh session after %ds (expiration period=%ds)",
		   (now.sec-inv->timer->last_refresh.sec),
		   inv->timer->setting.sess_expires));
    } else {
	
	pj_time_val now;

	/* Refreshee, terminate the session */
	status = pjsip_inv_end_session(inv, PJSIP_SC_REQUEST_TIMEOUT, 
				       NULL, &tdata);

	pj_gettimeofday(&now);
	PJ_LOG(3, (inv->pool->obj_name, 
		   "No session refresh received after %ds "
		   "(expiration period=%ds), stopping session now!",
		   (now.sec-inv->timer->last_refresh.sec),
		   inv->timer->setting.sess_expires));
    }

    /* Unlock dialog. */
    pjsip_dlg_dec_lock(inv->dlg);

    /* Send message, if any */
    if (tdata && status == PJ_SUCCESS) {
	status = pjsip_inv_send_msg(inv, tdata);
    }

    /* Print error message, if any */
    if (status != PJ_SUCCESS) {
	char errmsg[PJ_ERR_MSG_SIZE];

	if (tdata)
	    pjsip_tx_data_dec_ref(tdata);

	pj_strerror(status, errmsg, sizeof(errmsg));
	PJ_LOG(2, (inv->pool->obj_name, "Session timer fails in %s session, "
					"err code=%d (%s)",
					(as_refresher? "refreshing" : 
						       "terminating"),
					status, errmsg));					
    }
}