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

📄 presence.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 2 页
字号:
    pres->status.info_cnt = status->info_cnt;    return PJ_SUCCESS;}/* * Create message body. */static pj_status_t pres_create_msg_body( pjsip_pres *pres, 					 pjsip_tx_data *tdata){    pj_str_t entity;    /* Get publisher URI */    entity.ptr = pj_pool_alloc(tdata->pool, PJSIP_MAX_URL_SIZE);    entity.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI,				  pres->dlg->local.info->uri,				  entity.ptr, PJSIP_MAX_URL_SIZE);    if (entity.slen < 1)	return PJ_ENOMEM;    if (pres->content_type == CONTENT_TYPE_PIDF) {	return pjsip_pres_create_pidf(tdata->pool, &pres->status,				      &entity, &tdata->msg->body);    } else if (pres->content_type == CONTENT_TYPE_XPIDF) {	return pjsip_pres_create_xpidf(tdata->pool, &pres->status,				       &entity, &tdata->msg->body);    } else {	return PJSIP_SIMPLE_EBADCONTENT;    }}/* * Create NOTIFY */PJ_DEF(pj_status_t) pjsip_pres_notify( pjsip_evsub *sub,				       pjsip_evsub_state state,				       const pj_str_t *state_str,				       const pj_str_t *reason,				       pjsip_tx_data **p_tdata){    pjsip_pres *pres;    pjsip_tx_data *tdata;    pj_status_t status;        /* Check arguments. */    PJ_ASSERT_RETURN(sub, PJ_EINVAL);    /* Get the presence object. */    pres = pjsip_evsub_get_mod_data(sub, mod_presence.id);    PJ_ASSERT_RETURN(pres != NULL, PJSIP_SIMPLE_ENOPRESENCE);    /* Must have at least one presence info. */    PJ_ASSERT_RETURN(pres->status.info_cnt > 0, PJSIP_SIMPLE_ENOPRESENCEINFO);    /* Lock object. */    pjsip_dlg_inc_lock(pres->dlg);    /* Create the NOTIFY request. */    status = pjsip_evsub_notify( sub, state, state_str, reason, &tdata);    if (status != PJ_SUCCESS)	goto on_return;    /* Create message body to reflect the presence status. */    status = pres_create_msg_body( pres, tdata );    if (status != PJ_SUCCESS)	goto on_return;    /* Done. */    *p_tdata = tdata;on_return:    pjsip_dlg_dec_lock(pres->dlg);    return status;}/* * Create NOTIFY that reflect current state. */PJ_DEF(pj_status_t) pjsip_pres_current_notify( pjsip_evsub *sub,					       pjsip_tx_data **p_tdata ){    pjsip_pres *pres;    pjsip_tx_data *tdata;    pj_status_t status;        /* Check arguments. */    PJ_ASSERT_RETURN(sub, PJ_EINVAL);    /* Get the presence object. */    pres = pjsip_evsub_get_mod_data(sub, mod_presence.id);    PJ_ASSERT_RETURN(pres != NULL, PJSIP_SIMPLE_ENOPRESENCE);    /* Must have at least one presence info. */    PJ_ASSERT_RETURN(pres->status.info_cnt > 0, PJSIP_SIMPLE_ENOPRESENCEINFO);    /* Lock object. */    pjsip_dlg_inc_lock(pres->dlg);    /* Create the NOTIFY request. */    status = pjsip_evsub_current_notify( sub, &tdata);    if (status != PJ_SUCCESS)	goto on_return;    /* Create message body to reflect the presence status. */    status = pres_create_msg_body( pres, tdata );    if (status != PJ_SUCCESS)	goto on_return;    /* Done. */    *p_tdata = tdata;on_return:    pjsip_dlg_dec_lock(pres->dlg);    return status;}/* * Send request. */PJ_DEF(pj_status_t) pjsip_pres_send_request( pjsip_evsub *sub,					     pjsip_tx_data *tdata ){    return pjsip_evsub_send_request(sub, tdata);}/* * This callback is called by event subscription when subscription * state has changed. */static void pres_on_evsub_state( pjsip_evsub *sub, pjsip_event *event){    pjsip_pres *pres;    pres = pjsip_evsub_get_mod_data(sub, mod_presence.id);    PJ_ASSERT_ON_FAIL(pres!=NULL, {return;});    if (pres->user_cb.on_evsub_state)	(*pres->user_cb.on_evsub_state)(sub, event);}/* * Called when transaction state has changed. */static void pres_on_evsub_tsx_state( pjsip_evsub *sub, pjsip_transaction *tsx,				     pjsip_event *event){    pjsip_pres *pres;    pres = pjsip_evsub_get_mod_data(sub, mod_presence.id);    PJ_ASSERT_ON_FAIL(pres!=NULL, {return;});    if (pres->user_cb.on_tsx_state)	(*pres->user_cb.on_tsx_state)(sub, tsx, event);}/* * Called when SUBSCRIBE is received. */static void pres_on_evsub_rx_refresh( pjsip_evsub *sub, 				      pjsip_rx_data *rdata,				      int *p_st_code,				      pj_str_t **p_st_text,				      pjsip_hdr *res_hdr,				      pjsip_msg_body **p_body){    pjsip_pres *pres;    pres = pjsip_evsub_get_mod_data(sub, mod_presence.id);    PJ_ASSERT_ON_FAIL(pres!=NULL, {return;});    if (pres->user_cb.on_rx_refresh) {	(*pres->user_cb.on_rx_refresh)(sub, rdata, p_st_code, p_st_text,				       res_hdr, p_body);    } else {	/* Implementors MUST send NOTIFY if it implements on_rx_refresh */	pjsip_tx_data *tdata;	pj_str_t timeout = { "timeout", 7};	pj_status_t status;	if (pjsip_evsub_get_state(sub)==PJSIP_EVSUB_STATE_TERMINATED) {	    status = pjsip_pres_notify( sub, PJSIP_EVSUB_STATE_TERMINATED,					NULL, &timeout, &tdata);	} else {	    status = pjsip_pres_current_notify(sub, &tdata);	}	if (status == PJ_SUCCESS)	    pjsip_pres_send_request(sub, tdata);    }}/* * Process the content of incoming NOTIFY request and update temporary * status. * * return PJ_SUCCESS if incoming request is acceptable. If return value *	  is not PJ_SUCCESS, res_hdr may be added with Warning header. */static pj_status_t pres_process_rx_notify( pjsip_pres *pres,					   pjsip_rx_data *rdata, 					   int *p_st_code,					   pj_str_t **p_st_text,					   pjsip_hdr *res_hdr){    pjsip_ctype_hdr *ctype_hdr;    pj_status_t status;    *p_st_text = NULL;    /* Check Content-Type and msg body are present. */    ctype_hdr = rdata->msg_info.ctype;    if (ctype_hdr==NULL || rdata->msg_info.msg->body==NULL) {		pjsip_warning_hdr *warn_hdr;	pj_str_t warn_text;	*p_st_code = PJSIP_SC_BAD_REQUEST;	warn_text = pj_str("Message body is not present");	warn_hdr = pjsip_warning_hdr_create(rdata->tp_info.pool, 399,					    pjsip_endpt_name(pres->dlg->endpt),					    &warn_text);	pj_list_push_back(res_hdr, warn_hdr);	return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_REQUEST);    }    /* Parse content. */    if (pj_stricmp(&ctype_hdr->media.type, &STR_APPLICATION)==0 &&	pj_stricmp(&ctype_hdr->media.subtype, &STR_PIDF_XML)==0)    {	status = pjsip_pres_parse_pidf( rdata, pres->dlg->pool,					&pres->tmp_status);    }    else     if (pj_stricmp(&ctype_hdr->media.type, &STR_APPLICATION)==0 &&	pj_stricmp(&ctype_hdr->media.subtype, &STR_XPIDF_XML)==0)    {	status = pjsip_pres_parse_xpidf( rdata, pres->dlg->pool,					 &pres->tmp_status);    }    else    {	status = PJSIP_SIMPLE_EBADCONTENT;    }    if (status != PJ_SUCCESS) {	/* Unsupported or bad Content-Type */	pjsip_accept_hdr *accept_hdr;	pjsip_warning_hdr *warn_hdr;	*p_st_code = PJSIP_SC_NOT_ACCEPTABLE_HERE;	/* Add Accept header */	accept_hdr = pjsip_accept_hdr_create(rdata->tp_info.pool);	accept_hdr->values[accept_hdr->count++] = STR_APP_PIDF_XML;	accept_hdr->values[accept_hdr->count++] = STR_APP_XPIDF_XML;	pj_list_push_back(res_hdr, accept_hdr);	/* Add Warning header */	warn_hdr = pjsip_warning_hdr_create_from_status(				    rdata->tp_info.pool,				    pjsip_endpt_name(pres->dlg->endpt),				    status);	pj_list_push_back(res_hdr, warn_hdr);	return status;    }    /* If application calls pres_get_status(), redirect the call to     * retrieve the temporary status.     */    pres->tmp_status._is_valid = PJ_TRUE;    return PJ_SUCCESS;}/* * Called when NOTIFY is received. */static void pres_on_evsub_rx_notify( pjsip_evsub *sub, 				     pjsip_rx_data *rdata,				     int *p_st_code,				     pj_str_t **p_st_text,				     pjsip_hdr *res_hdr,				     pjsip_msg_body **p_body){    pjsip_pres *pres;    pj_status_t status;    pres = pjsip_evsub_get_mod_data(sub, mod_presence.id);    PJ_ASSERT_ON_FAIL(pres!=NULL, {return;});    if (rdata->msg_info.msg->body) {	status = pres_process_rx_notify( pres, rdata, p_st_code, p_st_text,					 res_hdr );	if (status != PJ_SUCCESS)	    return;    } else {	/* This has just been changed. Previously, we treat incoming NOTIFY	 * with no message body as having the presence subscription closed.	 * Now we treat it as no change in presence status (ref: EyeBeam).	 */#if 1	*p_st_code = 200;	return;#else	unsigned i;	/* Subscription is terminated. Consider contact is offline */	pres->tmp_status._is_valid = PJ_TRUE;	for (i=0; i<pres->tmp_status.info_cnt; ++i)	    pres->tmp_status.info[i].basic_open = PJ_FALSE;#endif    }    /* Notify application. */    if (pres->user_cb.on_rx_notify) {	(*pres->user_cb.on_rx_notify)(sub, rdata, p_st_code, p_st_text, 				      res_hdr, p_body);    }        /* If application responded NOTIFY with 2xx, copy temporary status     * to main status, and mark the temporary status as invalid.     */    if ((*p_st_code)/100 == 2) {	pj_memcpy(&pres->status, &pres->tmp_status, sizeof(pjsip_pres_status));    }    pres->tmp_status._is_valid = PJ_FALSE;    /* Done */}/* * Called when it's time to send SUBSCRIBE. */static void pres_on_evsub_client_refresh(pjsip_evsub *sub){    pjsip_pres *pres;    pres = pjsip_evsub_get_mod_data(sub, mod_presence.id);    PJ_ASSERT_ON_FAIL(pres!=NULL, {return;});    if (pres->user_cb.on_client_refresh) {	(*pres->user_cb.on_client_refresh)(sub);    } else {	pj_status_t status;	pjsip_tx_data *tdata;	status = pjsip_pres_initiate(sub, -1, &tdata);	if (status == PJ_SUCCESS)	    pjsip_pres_send_request(sub, tdata);    }}/* * Called when no refresh is received after the interval. */static void pres_on_evsub_server_timeout(pjsip_evsub *sub){    pjsip_pres *pres;    pres = pjsip_evsub_get_mod_data(sub, mod_presence.id);    PJ_ASSERT_ON_FAIL(pres!=NULL, {return;});    if (pres->user_cb.on_server_timeout) {	(*pres->user_cb.on_server_timeout)(sub);    } else {	pj_status_t status;	pjsip_tx_data *tdata;	pj_str_t reason = { "timeout", 7 };	status = pjsip_pres_notify(sub, PJSIP_EVSUB_STATE_TERMINATED,				   NULL, &reason, &tdata);	if (status == PJ_SUCCESS)	    pjsip_pres_send_request(sub, tdata);    }}

⌨️ 快捷键说明

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