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

📄 presence.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: presence.c 974 2007-02-19 01:13:53Z bennylp $ *//*  * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  */#include <pjsip-simple/presence.h>#include <pjsip-simple/errno.h>#include <pjsip-simple/evsub_msg.h>#include <pjsip/sip_module.h>#include <pjsip/sip_endpoint.h>#include <pjsip/sip_dialog.h>#include <pj/assert.h>#include <pj/guid.h>#include <pj/log.h>#include <pj/os.h>#include <pj/pool.h>#include <pj/string.h>#define THIS_FILE		    "presence.c"#define PRES_DEFAULT_EXPIRES	    600/* * Presence module (mod-presence) */static struct pjsip_module mod_presence = {    NULL, NULL,			    /* prev, next.			*/    { "mod-presence", 12 },	    /* Name.				*/    -1,				    /* Id				*/    PJSIP_MOD_PRIORITY_DIALOG_USAGE,/* Priority				*/    NULL,			    /* load()				*/    NULL,			    /* start()				*/    NULL,			    /* stop()				*/    NULL,			    /* unload()				*/    NULL,			    /* on_rx_request()			*/    NULL,			    /* on_rx_response()			*/    NULL,			    /* on_tx_request.			*/    NULL,			    /* on_tx_response()			*/    NULL,			    /* on_tsx_state()			*/};/* * Presence message body type. */typedef enum content_type{    CONTENT_TYPE_NONE,    CONTENT_TYPE_PIDF,    CONTENT_TYPE_XPIDF,} content_type;/* * This structure describe a presentity, for both subscriber and notifier. */struct pjsip_pres{    pjsip_evsub		*sub;		/**< Event subscribtion record.	    */    pjsip_dialog	*dlg;		/**< The dialog.		    */    content_type	 content_type;	/**< Content-Type.		    */    pjsip_pres_status	 status;	/**< Presence status.		    */    pjsip_pres_status	 tmp_status;	/**< Temp, before NOTIFY is answred.*/    pjsip_evsub_user	 user_cb;	/**< The user callback.		    */};typedef struct pjsip_pres pjsip_pres;/* * Forward decl for evsub callback. */static void pres_on_evsub_state( pjsip_evsub *sub, pjsip_event *event);static void pres_on_evsub_tsx_state( pjsip_evsub *sub, pjsip_transaction *tsx,				     pjsip_event *event);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);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);static void pres_on_evsub_client_refresh(pjsip_evsub *sub);static void pres_on_evsub_server_timeout(pjsip_evsub *sub);/* * Event subscription callback for presence. */static pjsip_evsub_user pres_user = {    &pres_on_evsub_state,    &pres_on_evsub_tsx_state,    &pres_on_evsub_rx_refresh,    &pres_on_evsub_rx_notify,    &pres_on_evsub_client_refresh,    &pres_on_evsub_server_timeout,};/* * Some static constants. */const pj_str_t STR_EVENT	    = { "Event", 5 };const pj_str_t STR_PRESENCE	    = { "presence", 8 };const pj_str_t STR_APPLICATION	    = { "application", 11 };const pj_str_t STR_PIDF_XML	    = { "pidf+xml", 8};const pj_str_t STR_XPIDF_XML	    = { "xpidf+xml", 9};const pj_str_t STR_APP_PIDF_XML	    = { "application/pidf+xml", 20 };const pj_str_t STR_APP_XPIDF_XML    = { "application/xpidf+xml", 21 };/* * Init presence module. */PJ_DEF(pj_status_t) pjsip_pres_init_module( pjsip_endpoint *endpt,					    pjsip_module *mod_evsub){    pj_status_t status;    pj_str_t accept[2];    /* Check arguments. */    PJ_ASSERT_RETURN(endpt && mod_evsub, PJ_EINVAL);    /* Must have not been registered */    PJ_ASSERT_RETURN(mod_presence.id == -1, PJ_EINVALIDOP);    /* Register to endpoint */    status = pjsip_endpt_register_module(endpt, &mod_presence);    if (status != PJ_SUCCESS)	return status;    accept[0] = STR_APP_PIDF_XML;    accept[1] = STR_APP_XPIDF_XML;    /* Register event package to event module. */    status = pjsip_evsub_register_pkg( &mod_presence, &STR_PRESENCE, 				       PRES_DEFAULT_EXPIRES, 				       PJ_ARRAY_SIZE(accept), accept);    if (status != PJ_SUCCESS) {	pjsip_endpt_unregister_module(endpt, &mod_presence);	return status;    }    return PJ_SUCCESS;}/* * Get presence module instance. */PJ_DEF(pjsip_module*) pjsip_pres_instance(void){    return &mod_presence;}/* * Create client subscription. */PJ_DEF(pj_status_t) pjsip_pres_create_uac( pjsip_dialog *dlg,					   const pjsip_evsub_user *user_cb,					   unsigned options,					   pjsip_evsub **p_evsub ){    pj_status_t status;    pjsip_pres *pres;    pjsip_evsub *sub;    PJ_ASSERT_RETURN(dlg && p_evsub, PJ_EINVAL);    pjsip_dlg_inc_lock(dlg);    /* Create event subscription */    status = pjsip_evsub_create_uac( dlg,  &pres_user, &STR_PRESENCE, 				     options, &sub);    if (status != PJ_SUCCESS)	goto on_return;    /* Create presence */    pres = pj_pool_zalloc(dlg->pool, sizeof(pjsip_pres));    pres->dlg = dlg;    pres->sub = sub;    if (user_cb)	pj_memcpy(&pres->user_cb, user_cb, sizeof(pjsip_evsub_user));    /* Attach to evsub */    pjsip_evsub_set_mod_data(sub, mod_presence.id, pres);    *p_evsub = sub;on_return:    pjsip_dlg_dec_lock(dlg);    return status;}/* * Create server subscription. */PJ_DEF(pj_status_t) pjsip_pres_create_uas( pjsip_dialog *dlg,					   const pjsip_evsub_user *user_cb,					   pjsip_rx_data *rdata,					   pjsip_evsub **p_evsub ){    pjsip_accept_hdr *accept;    pjsip_event_hdr *event;    pjsip_expires_hdr *expires_hdr;    unsigned expires;    content_type content_type = CONTENT_TYPE_NONE;    pjsip_evsub *sub;    pjsip_pres *pres;    pj_status_t status;    /* Check arguments */    PJ_ASSERT_RETURN(dlg && rdata && p_evsub, PJ_EINVAL);    /* Must be request message */    PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_REQUEST_MSG,		     PJSIP_ENOTREQUESTMSG);    /* Check that request is SUBSCRIBE */    PJ_ASSERT_RETURN(pjsip_method_cmp(&rdata->msg_info.msg->line.req.method,				      &pjsip_subscribe_method)==0,		     PJSIP_SIMPLE_ENOTSUBSCRIBE);    /* Check that Event header contains "presence" */    event = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &STR_EVENT, NULL);    if (!event) {	return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_REQUEST);    }    if (pj_stricmp(&event->event_type, &STR_PRESENCE) != 0) {	return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_EVENT);    }    /* Check that request contains compatible Accept header. */    accept = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_ACCEPT, NULL);    if (accept) {	unsigned i;	for (i=0; i<accept->count; ++i) {	    if (pj_stricmp(&accept->values[i], &STR_APP_PIDF_XML)==0) {		content_type = CONTENT_TYPE_PIDF;		break;	    } else	    if (pj_stricmp(&accept->values[i], &STR_APP_XPIDF_XML)==0) {		content_type = CONTENT_TYPE_XPIDF;		break;	    }	}	if (i==accept->count) {	    /* Nothing is acceptable */	    return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_NOT_ACCEPTABLE);	}    } else {	/* No Accept header.	 * Treat as "application/pidf+xml"	 */	content_type = CONTENT_TYPE_PIDF;    }    /* Check that expires is not too short. */    expires_hdr=pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL);    if (expires_hdr) {	if (expires_hdr->ivalue < 5) {	    return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_INTERVAL_TOO_BRIEF);	}	expires = expires_hdr->ivalue;	if (expires > PRES_DEFAULT_EXPIRES)	    expires = PRES_DEFAULT_EXPIRES;    } else {	expires = PRES_DEFAULT_EXPIRES;    }        /* Lock dialog */    pjsip_dlg_inc_lock(dlg);    /* Create server subscription */    status = pjsip_evsub_create_uas( dlg, &pres_user, rdata, 0, &sub);    if (status != PJ_SUCCESS)	goto on_return;    /* Create server presence subscription */    pres = pj_pool_zalloc(dlg->pool, sizeof(pjsip_pres));    pres->dlg = dlg;    pres->sub = sub;    pres->content_type = content_type;    if (user_cb)	pj_memcpy(&pres->user_cb, user_cb, sizeof(pjsip_evsub_user));    /* Attach to evsub */    pjsip_evsub_set_mod_data(sub, mod_presence.id, pres);    /* Done: */    *p_evsub = sub;on_return:    pjsip_dlg_dec_lock(dlg);    return status;}/* * Forcefully terminate presence. */PJ_DEF(pj_status_t) pjsip_pres_terminate( pjsip_evsub *sub,					  pj_bool_t notify ){    return pjsip_evsub_terminate(sub, notify);}/* * Create SUBSCRIBE */PJ_DEF(pj_status_t) pjsip_pres_initiate( pjsip_evsub *sub,					 pj_int32_t expires,					 pjsip_tx_data **p_tdata){    return pjsip_evsub_initiate(sub, &pjsip_subscribe_method, expires, 				p_tdata);}/* * Accept incoming subscription. */PJ_DEF(pj_status_t) pjsip_pres_accept( pjsip_evsub *sub,				       pjsip_rx_data *rdata,				       int st_code,				       const pjsip_hdr *hdr_list ){    return pjsip_evsub_accept( sub, rdata, st_code, hdr_list );}/* * Get presence status. */PJ_DEF(pj_status_t) pjsip_pres_get_status( pjsip_evsub *sub,					   pjsip_pres_status *status ){    pjsip_pres *pres;    PJ_ASSERT_RETURN(sub && status, PJ_EINVAL);    pres = pjsip_evsub_get_mod_data(sub, mod_presence.id);    PJ_ASSERT_RETURN(pres!=NULL, PJSIP_SIMPLE_ENOPRESENCE);    if (pres->tmp_status._is_valid)	pj_memcpy(status, &pres->tmp_status, sizeof(pjsip_pres_status));    else	pj_memcpy(status, &pres->status, sizeof(pjsip_pres_status));    return PJ_SUCCESS;}/* * Set presence status. */PJ_DEF(pj_status_t) pjsip_pres_set_status( pjsip_evsub *sub,					   const pjsip_pres_status *status ){    unsigned i;    pjsip_pres *pres;    PJ_ASSERT_RETURN(sub && status, PJ_EINVAL);    pres = pjsip_evsub_get_mod_data(sub, mod_presence.id);    PJ_ASSERT_RETURN(pres!=NULL, PJSIP_SIMPLE_ENOPRESENCE);    for (i=0; i<status->info_cnt; ++i) {	pres->status.info[i].basic_open = status->info[i].basic_open;	if (status->info[i].id.slen == 0) {	    pj_create_unique_string(pres->dlg->pool, 	    			    &pres->status.info[i].id);	} else {	    pj_strdup(pres->dlg->pool, 		      &pres->status.info[i].id,		      &status->info[i].id);	}	pj_strdup(pres->dlg->pool, 		  &pres->status.info[i].contact,		  &status->info[i].contact);    }

⌨️ 快捷键说明

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