⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 evsub.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	    return;	}	/* Only interested in final response */	if (tsx->state != PJSIP_TSX_STATE_COMPLETED &&	    tsx->state != PJSIP_TSX_STATE_TERMINATED)	{	    return;	}	/* Clear pending subscription */	if (tsx == sub->pending_sub)	    sub->pending_sub = NULL;	/* Handle authentication. */	if (tsx->status_code==401 || tsx->status_code==407) {	    pjsip_tx_data *tdata;	    pj_status_t status;	    if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {		/* Previously failed transaction has terminated */		return;	    }	    status = pjsip_auth_clt_reinit_req(&sub->dlg->auth_sess,					       event->body.tsx_state.src.rdata,					       tsx->last_tx, &tdata);	    if (status == PJ_SUCCESS) 		status = pjsip_dlg_send_request(sub->dlg, tdata, -1, NULL);	    	    if (status != PJ_SUCCESS) {		/* Authentication failed! */		set_state(sub, PJSIP_EVSUB_STATE_TERMINATED,			       NULL,			       event);		return;	    }	    return;	}	if (tsx->status_code/100 == 2) {	    /* Successfull SUBSCRIBE request! 	     * This could be:	     *	- response to initial SUBSCRIBE request	     *	- response to subsequent refresh	     *	- response to unsubscription	     */	    if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {		/* Ignore; this transaction has been processed before */		return;	    }	    /* Update UAC refresh time, if response contains Expires header,	     * only when we're not unsubscribing. 	     */	    if (sub->expires->ivalue != 0) {		pjsip_msg *msg;		pjsip_expires_hdr *expires;		msg = event->body.tsx_state.src.rdata->msg_info.msg;		expires = pjsip_msg_find_hdr(msg, PJSIP_H_EXPIRES, NULL);		if (expires) {		    sub->expires->ivalue = expires->ivalue;		}	    }	    /* Update time */	    update_expires(sub, sub->expires->ivalue);	    /* Start UAC refresh timer, only when we're not unsubscribing */	    if (sub->expires->ivalue != 0) {		unsigned timeout = (sub->expires->ivalue > TIME_UAC_REFRESH) ?		    sub->expires->ivalue - TIME_UAC_REFRESH : sub->expires->ivalue;		PJ_LOG(5,(sub->obj_name, "Will refresh in %d seconds", 			  timeout));		set_timer(sub, TIMER_TYPE_UAC_REFRESH, timeout);	    } else {		/* Otherwise set timer to terminate client subscription when		 * NOTIFY to end subscription is not received.		 */		set_timer(sub, TIMER_TYPE_UAC_TERMINATE, TIME_UAC_TERMINATE);	    }	    	    /* Set state, if necessary */	    pj_assert(sub->state != PJSIP_EVSUB_STATE_NULL);	    if (sub->state == PJSIP_EVSUB_STATE_SENT) {		set_state(sub, PJSIP_EVSUB_STATE_ACCEPTED, NULL, event);	    }	} else {	    /* Failed SUBSCRIBE request! 	     *	     * The RFC 3265 says that if outgoing SUBSCRIBE fails with status	     * other than 481, the subscription is still considered valid for	     * the duration of the last Expires.	     *	     * Since we send refresh about 5 seconds (TIME_UAC_REFRESH) before 	     * expiration, theoritically the expiration is still valid for the 	     * next 5 seconds even when we receive non-481 failed response.	     *	     * Ah, what the heck!	     *	     * Just terminate now!	     *	     */	    if (sub->state == PJSIP_EVSUB_STATE_TERMINATED) {		/* Ignore, has been handled before */		return;	    }	    /* Ignore 490 (Request Updated) status. 	     * This happens when application sends SUBSCRIBE/REFER while 	     * another one is still in progress.	     */	    if (tsx->status_code == PJSIP_SC_REQUEST_UPDATED) {		return;	    }	    /* Kill any timer. */	    set_timer(sub, TIMER_TYPE_NONE, 0);	    /* Set state to TERMINATED */	    set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, 		      NULL, event);	}    } else if (pjsip_method_cmp(&tsx->method, &pjsip_notify_method) == 0) {	/* Incoming NOTIFY. 	 * This can be the result of:	 *  - Initial subscription response	 *  - UAS updating the resource info.	 *  - Unsubscription response.	 */	int st_code = 200;	pj_str_t *st_text = NULL;	pjsip_hdr res_hdr;	pjsip_msg_body *body = NULL;	pjsip_rx_data *rdata;	pjsip_msg *msg;	pjsip_sub_state_hdr *sub_state;	pjsip_evsub_state new_state;	pj_str_t *new_state_str;	pjsip_tx_data *tdata;	pj_status_t status;	int next_refresh;	/* Only want to handle initial NOTIFY receive event. */	if (tsx->state != PJSIP_TSX_STATE_TRYING)	    return;	rdata = event->body.tsx_state.src.rdata;	msg = rdata->msg_info.msg;	pj_list_init(&res_hdr);	/* Get subscription state header. */	sub_state = pjsip_msg_find_hdr_by_name(msg, &STR_SUB_STATE, NULL);	if (sub_state == NULL) {	    pjsip_warning_hdr *warn_hdr;	    pj_str_t warn_text = { "Missing Subscription-State header", 33};	    /* Bad request! Add warning header. */	    st_code = PJSIP_SC_BAD_REQUEST;	    warn_hdr = pjsip_warning_hdr_create(rdata->tp_info.pool, 399,					        pjsip_endpt_name(sub->endpt),						&warn_text);	    pj_list_push_back(&res_hdr, warn_hdr);	}	/* Call application registered callback to handle incoming NOTIFY,	 * if any.	 */	if (st_code==200 && sub->user.on_rx_notify && sub->call_cb) {	    (*sub->user.on_rx_notify)(sub, rdata, &st_code, &st_text, 				      &res_hdr, &body);	    /* Application MUST specify final response! */	    PJ_ASSERT_ON_FAIL(st_code >= 200, {st_code=200; });	    /* Must be a valid status code */	    PJ_ASSERT_ON_FAIL(st_code <= 699, {st_code=500; });	}	/* If non-2xx should be returned, then send the response.	 * No need to update server subscription state.	 */	if (st_code >= 300) {	    status = create_response(sub, rdata, st_code, st_text, &res_hdr,				     body, &tdata);	    if (status == PJ_SUCCESS) {		status = pjsip_dlg_send_response(sub->dlg, tsx, tdata);	    }	    /* Start timer to terminate subscription, just in case server	     * is not able to generate NOTIFY to our response.	     */	    if (status == PJ_SUCCESS) {		unsigned timeout = TIME_UAC_WAIT_NOTIFY;		set_timer(sub, TIMER_TYPE_UAC_WAIT_NOTIFY, timeout);	    } else {		set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, NULL);	    }	    return;	}	/* Update expiration from the value of expires param in	 * Subscription-State header, but ONLY when subscription state 	 * is "active" or "pending", AND the header contains expires param.	 */	if (sub->expires->ivalue != 0 &&	    sub_state->expires_param >= 0 &&	    (pj_stricmp(&sub_state->sub_state, &STR_ACTIVE)==0 ||	     pj_stricmp(&sub_state->sub_state, &STR_PENDING)==0))	{	    next_refresh = sub_state->expires_param;	} else {	    next_refresh = sub->expires->ivalue;	}	/* Update time */	update_expires(sub, next_refresh);	/* Start UAC refresh timer, only when we're not unsubscribing */	if (sub->expires->ivalue != 0) {	    unsigned timeout = (next_refresh > TIME_UAC_REFRESH) ?		next_refresh - TIME_UAC_REFRESH : next_refresh;	    PJ_LOG(5,(sub->obj_name, "Will refresh in %d seconds", timeout));	    set_timer(sub, TIMER_TYPE_UAC_REFRESH, timeout);	}		/* Find out the state */	get_hdr_state(sub_state, &new_state, &new_state_str);	/* Send response. */	status = create_response(sub, rdata, st_code, st_text, &res_hdr,				 body, &tdata);	if (status == PJ_SUCCESS)	    status = pjsip_dlg_send_response(sub->dlg, tsx, tdata);	/* Set the state */	if (status == PJ_SUCCESS) {	    set_state(sub, new_state, new_state_str, event);	} else {	    set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, event);	}    } else {	/*	 * Unexpected method!	 */	PJ_LOG(4,(sub->obj_name, "Unexpected transaction method %.*s",		 (int)tsx->method.name.slen, tsx->method.name.ptr));    }}/* * Transaction event processing by UAS, after subscription is accepted. */static void on_tsx_state_uas( pjsip_evsub *sub, pjsip_transaction *tsx,			      pjsip_event *event){    if (pjsip_method_cmp(&tsx->method, &sub->method) == 0 ||	pjsip_method_cmp(&tsx->method, &pjsip_subscribe_method) == 0)     {		/*	 * Incoming request (e.g. SUBSCRIBE or REFER) to refresh subsciption.	 *	 */	pjsip_rx_data *rdata;	pjsip_event_hdr *event_hdr;	pjsip_expires_hdr *expires;	pjsip_msg *msg;	pjsip_tx_data *tdata;	int st_code = 200;	pj_str_t *st_text = NULL;	pjsip_hdr res_hdr;	pjsip_msg_body *body = NULL;	pjsip_evsub_state old_state;	pj_str_t old_state_str;	pj_status_t status;	/* Only wants to handle the first event when the request is 	 * received.	 */	if (tsx->state != PJSIP_TSX_STATE_TRYING)	    return;	rdata = event->body.tsx_state.src.rdata;	msg = rdata->msg_info.msg;	/* Set expiration time based on client request (in Expires header),	 * or package default expiration time.	 */	event_hdr = pjsip_msg_find_hdr_by_name(msg, &STR_EVENT, NULL);	expires = pjsip_msg_find_hdr(msg, PJSIP_H_EXPIRES, NULL);	if (event_hdr && expires) {	    struct evpkg *evpkg;	    evpkg = find_pkg(&event_hdr->event_type);	    if (evpkg) {		if (expires->ivalue < (pj_int32_t)evpkg->pkg_expires)		    sub->expires->ivalue = expires->ivalue;		else		    sub->expires->ivalue = evpkg->pkg_expires;	    }	}		/* Update time (before calling on_rx_refresh, since application	 * will send NOTIFY.	 */	update_expires(sub, sub->expires->ivalue);	/* Save old state.	 * If application respond with non-2xx, revert to old state.	 */	old_state = sub->state;	old_state_str = sub->state_str;	if (sub->expires->ivalue == 0) {	    sub->state = PJSIP_EVSUB_STATE_TERMINATED;	    sub->state_str = evsub_state_names[sub->state];	} else  if (sub->state == PJSIP_EVSUB_STATE_NULL) {	    sub->state = PJSIP_EVSUB_STATE_ACCEPTED;	    sub->state_str = evsub_state_names[sub->state];	}	/* Call application's on_rx_refresh, just in case it wants to send	 * response other than 200 (OK)	 */	pj_list_init(&res_hdr);	if (sub->user.on_rx_refresh && sub->call_cb) {	    (*sub->user.on_rx_refresh)(sub, rdata, &st_code, &st_text, 				       &res_hdr, &body);	}	/* Application MUST specify final response! */	PJ_ASSERT_ON_FAIL(st_code >= 200, {st_code=200; });	/* Must be a valid status code */	PJ_ASSERT_ON_FAIL(st_code <= 699, {st_code=500; });	/* Create and send response */	status = create_response(sub, rdata, st_code, st_text, &res_hdr,				 body, &tdata);	if (status == PJ_SUCCESS) {	    /* Add expires header: */	    pjsip_msg_add_hdr( tdata->msg,			       pjsip_hdr_shallow_clone(tdata->pool, 						       sub->expires));	    /* Send */	    status = pjsip_dlg_send_response(sub->dlg, tsx, tdata);	}	/* Update state or revert state */	if (st_code/100==2) {	    	    if (sub->expires->ivalue == 0) {		set_state(sub, sub->state, NULL, event);	    } else  if (sub->state == PJSIP_EVSUB_STATE_NULL) {		set_state(sub, sub->state, NULL, event);	    }	    /* Set UAS timeout timer, when state is not terminated. */	    if (sub->state != PJSIP_EVSUB_STATE_TERMINATED) {		PJ_LOG(5,(sub->obj_name, "UAS timeout in %d seconds",			  sub->expires->ivalue));		set_timer(sub, TIMER_TYPE_UAS_TIMEOUT, 			  sub->expires->ivalue);	    }	}  else {	    sub->state = old_state;	    sub->state_str = old_state_str;	}    } else if (pjsip_method_cmp(&tsx->method, &pjsip_notify_method)==0) {	/* Handle authentication */ 	if (tsx->state == PJSIP_TSX_STATE_COMPLETED &&	    (tsx->status_code==401 || tsx->status_code==407))	{	    pjsip_rx_data *rdata = event->body.tsx_state.src.rdata;	    pjsip_tx_data *tdata;	    pj_status_t status;	    status = pjsip_auth_clt_reinit_req( &sub->dlg->auth_sess, rdata, 						tsx->last_tx, &tdata);	    if (status == PJ_SUCCESS)		status = pjsip_dlg_send_request( sub->dlg, tdata, -1, NULL );	    if (status != PJ_SUCCESS) {		/* Can't authenticate. Terminate session (?) */		set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, NULL);		return;	    }	}	/*	 * Terminate event usage if we receive 481, 408, and 7 class	 * responses.	 */	if (sub->state != PJSIP_EVSUB_STATE_TERMINATED &&	    (tsx->status_code==481 || tsx->status_code==408 ||	     tsx->status_code/100 == 7))	{	    set_state(sub, PJSIP_EVSUB_STATE_TERMINATED, NULL, event);	    return;	}    } else {	/*	 * Unexpected method!	 */	PJ_LOG(4,(sub->obj_name, "Unexpected transaction method %.*s",		 (int)tsx->method.name.slen, tsx->method.name.ptr));        }}/* * Notification when transaction state has changed! */static void mod_evsub_on_tsx_state(pjsip_transaction *tsx, pjsip_event *event){    pjsip_evsub *sub = pjsip_tsx_get_evsub(tsx);    if (sub == NULL) {	sub = on_new_transaction(tsx, event);	if (sub == NULL)	    return;    }    /* Call on_tsx_state callback, if any. */    if (sub->user.on_tsx_state && sub->call_cb)	(*sub->user.on_tsx_state)(sub, tsx, event);    /* Process the event: */    if (sub->role == PJSIP_ROLE_UAC) {	on_tsx_state_uac(sub, tsx, event);    } else {	on_tsx_state_uas(sub, tsx, event);    }    /* Check transaction TERMINATE event */    if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {	--sub->pending_tsx;	if (sub->state == PJSIP_EVSUB_STATE_TERMINATED &&	    sub->pending_tsx == 0)	{	    evsub_destroy(sub);	}    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -