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

📄 sip_dialog.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* $Id: sip_dialog.c 1027 2007-03-01 18:41:36Z 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/sip_dialog.h>#include <pjsip/sip_ua_layer.h>#include <pjsip/sip_errno.h>#include <pjsip/sip_endpoint.h>#include <pjsip/sip_parser.h>#include <pjsip/sip_module.h>#include <pjsip/sip_util.h>#include <pjsip/sip_transaction.h>#include <pj/assert.h>#include <pj/os.h>#include <pj/string.h>#include <pj/pool.h>#include <pj/guid.h>#include <pj/rand.h>#include <pj/array.h>#include <pj/except.h>#include <pj/hash.h>#include <pj/log.h>#define THIS_FILE	"sip_dialog.c"long pjsip_dlg_lock_tls_id;PJ_DEF(pj_bool_t) pjsip_method_creates_dialog(const pjsip_method *m){    const pjsip_method subscribe = { PJSIP_OTHER_METHOD, {"SUBSCRIBE", 9}};    const pjsip_method refer = { PJSIP_OTHER_METHOD, {"REFER", 5}};    const pjsip_method notify = { PJSIP_OTHER_METHOD, {"NOTIFY", 6}};    return m->id == PJSIP_INVITE_METHOD ||	   (pjsip_method_cmp(m, &subscribe)==0) ||	   (pjsip_method_cmp(m, &refer)==0) ||	   (pjsip_method_cmp(m, &notify)==0);}static pj_status_t create_dialog( pjsip_user_agent *ua,				  pjsip_dialog **p_dlg){    pjsip_endpoint *endpt;    pj_pool_t *pool;    pjsip_dialog *dlg;    pj_status_t status;    endpt = pjsip_ua_get_endpt(ua);    if (!endpt)	return PJ_EINVALIDOP;    pool = pjsip_endpt_create_pool(endpt, "dlg%p", 				   PJSIP_POOL_LEN_DIALOG, 				   PJSIP_POOL_INC_DIALOG);    if (!pool)	return PJ_ENOMEM;    dlg = pj_pool_zalloc(pool, sizeof(pjsip_dialog));    PJ_ASSERT_RETURN(dlg != NULL, PJ_ENOMEM);    dlg->pool = pool;    pj_ansi_snprintf(dlg->obj_name, sizeof(dlg->obj_name), "dlg%p", dlg);    dlg->ua = ua;    dlg->endpt = endpt;    dlg->state = PJSIP_DIALOG_STATE_NULL;    pj_list_init(&dlg->inv_hdr);    status = pj_mutex_create_recursive(pool, dlg->obj_name, &dlg->mutex_);    if (status != PJ_SUCCESS)	goto on_error;    *p_dlg = dlg;    return PJ_SUCCESS;on_error:    if (dlg->mutex_)	pj_mutex_destroy(dlg->mutex_);    pjsip_endpt_release_pool(endpt, pool);    return status;}static void destroy_dialog( pjsip_dialog *dlg ){    if (dlg->mutex_) {	pj_mutex_destroy(dlg->mutex_);	dlg->mutex_ = NULL;    }    if (dlg->tp_sel.type != PJSIP_TPSELECTOR_NONE) {	pjsip_tpselector_dec_ref(&dlg->tp_sel);	pj_bzero(&dlg->tp_sel, sizeof(pjsip_tpselector));    }    pjsip_endpt_release_pool(dlg->endpt, dlg->pool);}/* * Create an UAC dialog. */PJ_DEF(pj_status_t) pjsip_dlg_create_uac( pjsip_user_agent *ua,					  const pj_str_t *local_uri,					  const pj_str_t *local_contact,					  const pj_str_t *remote_uri,					  const pj_str_t *target,					  pjsip_dialog **p_dlg){    pj_status_t status;    pj_str_t tmp;    pjsip_dialog *dlg;    /* Check arguments. */    PJ_ASSERT_RETURN(ua && local_uri && remote_uri && p_dlg, PJ_EINVAL);    /* Create dialog instance. */    status = create_dialog(ua, &dlg);    if (status != PJ_SUCCESS)	return status;    /* Parse target. */    pj_strdup_with_null(dlg->pool, &tmp, target ? target : remote_uri);    dlg->target = pjsip_parse_uri(dlg->pool, tmp.ptr, tmp.slen, 0);    if (!dlg->target) {	status = PJSIP_EINVALIDURI;	goto on_error;    }    /* Put any header param in the target URI into INVITE header list. */    if (PJSIP_URI_SCHEME_IS_SIP(dlg->target) ||	PJSIP_URI_SCHEME_IS_SIPS(dlg->target))    {	pjsip_param *param;	pjsip_sip_uri *uri = (pjsip_sip_uri*)pjsip_uri_get_uri(dlg->target);	param = uri->header_param.next;	while (param != &uri->header_param) {	    pjsip_hdr *hdr;	    int c;	    c = param->value.ptr[param->value.slen];	    param->value.ptr[param->value.slen] = '\0';	    hdr = pjsip_parse_hdr(dlg->pool, &param->name, param->value.ptr,				  param->value.slen, NULL);	    param->value.ptr[param->value.slen] = (char)c;	    if (hdr == NULL) {		status = PJSIP_EINVALIDURI;		goto on_error;	    }	    pj_list_push_back(&dlg->inv_hdr, hdr);	    param = param->next;	}	/* Now must remove any header params from URL, since that would	 * create another header in pjsip_endpt_create_request().	 */	pj_list_init(&uri->header_param);    }    /* Init local info. */    dlg->local.info = pjsip_from_hdr_create(dlg->pool);    pj_strdup_with_null(dlg->pool, &dlg->local.info_str, local_uri);    dlg->local.info->uri = pjsip_parse_uri(dlg->pool, 					   dlg->local.info_str.ptr, 					   dlg->local.info_str.slen, 0);    if (!dlg->local.info->uri) {	status = PJSIP_EINVALIDURI;	goto on_error;    }    /* Generate local tag. */    pj_create_unique_string(dlg->pool, &dlg->local.info->tag);    /* Calculate hash value of local tag. */    dlg->local.tag_hval = pj_hash_calc(0, dlg->local.info->tag.ptr,				       dlg->local.info->tag.slen);    /* Randomize local CSeq. */    dlg->local.first_cseq = pj_rand() % 0x7FFFFFFFL;    dlg->local.cseq = dlg->local.first_cseq;    /* Init local contact. */    dlg->local.contact = pjsip_contact_hdr_create(dlg->pool);    pj_strdup_with_null(dlg->pool, &tmp, 			local_contact ? local_contact : local_uri);    dlg->local.contact->uri = pjsip_parse_uri(dlg->pool, tmp.ptr, tmp.slen,					      PJSIP_PARSE_URI_AS_NAMEADDR);    if (!dlg->local.contact->uri) {	status = PJSIP_EINVALIDURI;	goto on_error;    }    /* Init remote info. */    dlg->remote.info = pjsip_to_hdr_create(dlg->pool);    pj_strdup_with_null(dlg->pool, &dlg->remote.info_str, remote_uri);    dlg->remote.info->uri = pjsip_parse_uri(dlg->pool, 					    dlg->remote.info_str.ptr, 					    dlg->remote.info_str.slen, 0);    if (!dlg->remote.info->uri) {	status = PJSIP_EINVALIDURI;	goto on_error;    }    /* Remove header param from remote.info_str, if any */    if (PJSIP_URI_SCHEME_IS_SIP(dlg->remote.info->uri) ||	PJSIP_URI_SCHEME_IS_SIPS(dlg->remote.info->uri))    {	pjsip_sip_uri *sip_uri = pjsip_uri_get_uri(dlg->remote.info->uri);	if (!pj_list_empty(&sip_uri->header_param)) {	    pj_str_t tmp;	    /* Remove all header param */	    pj_list_init(&sip_uri->header_param);	    /* Print URI */	    tmp.ptr = pj_pool_alloc(dlg->pool, dlg->remote.info_str.slen);	    tmp.slen = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR,				       sip_uri, tmp.ptr, 				       dlg->remote.info_str.slen);	    if (tmp.slen < 1) {		status = PJSIP_EURITOOLONG;		goto on_error;	    }	    /* Assign remote.info_str */	    dlg->remote.info_str = tmp;	}    }    /* Initialize remote's CSeq to -1. */    dlg->remote.cseq = dlg->remote.first_cseq = -1;    /* Initial role is UAC. */    dlg->role = PJSIP_ROLE_UAC;    /* Secure? */    dlg->secure = PJSIP_URI_SCHEME_IS_SIPS(dlg->target);    /* Generate Call-ID header. */    dlg->call_id = pjsip_cid_hdr_create(dlg->pool);    pj_create_unique_string(dlg->pool, &dlg->call_id->id);    /* Initial route set is empty. */    pj_list_init(&dlg->route_set);    /* Init client authentication session. */    status = pjsip_auth_clt_init(&dlg->auth_sess, dlg->endpt, 				 dlg->pool, 0);    if (status != PJ_SUCCESS)	goto on_error;    /* Register this dialog to user agent. */    status = pjsip_ua_register_dlg( ua, dlg );    if (status != PJ_SUCCESS)	goto on_error;    /* Done! */    *p_dlg = dlg;    PJ_LOG(5,(dlg->obj_name, "UAC dialog created"));    return PJ_SUCCESS;on_error:    destroy_dialog(dlg);    return status;}/* * Create UAS dialog. */PJ_DEF(pj_status_t) pjsip_dlg_create_uas(   pjsip_user_agent *ua,					    pjsip_rx_data *rdata,					    const pj_str_t *contact,					    pjsip_dialog **p_dlg){    pj_status_t status;    pjsip_hdr *contact_hdr;    pjsip_rr_hdr *rr;    pjsip_transaction *tsx = NULL;    pj_str_t tmp;    enum { TMP_LEN=128};    pj_ssize_t len;    pjsip_dialog *dlg;    /* Check arguments. */    PJ_ASSERT_RETURN(ua && rdata && p_dlg, PJ_EINVAL);    /* rdata must have request message. */    PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_REQUEST_MSG,		     PJSIP_ENOTREQUESTMSG);    /* Request must not have To tag.      * This should have been checked in the user agent (or application?).     */    PJ_ASSERT_RETURN(rdata->msg_info.to->tag.slen == 0, PJ_EINVALIDOP);		         /* The request must be a dialog establishing request. */    PJ_ASSERT_RETURN(	pjsip_method_creates_dialog(&rdata->msg_info.msg->line.req.method),	PJ_EINVALIDOP);    /* Create dialog instance. */    status = create_dialog(ua, &dlg);    if (status != PJ_SUCCESS)	return status;    /* Temprary string for getting the string representation of     * both local and remote URI.     */    tmp.ptr = pj_pool_alloc(rdata->tp_info.pool, TMP_LEN);    /* Init local info from the To header. */    dlg->local.info = pjsip_hdr_clone(dlg->pool, rdata->msg_info.to);    pjsip_fromto_hdr_set_from(dlg->local.info);    /* Generate local tag. */    pj_create_unique_string(dlg->pool, &dlg->local.info->tag);    /* Print the local info. */    len = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR,			  dlg->local.info->uri, tmp.ptr, TMP_LEN);    if (len < 1) {	pj_ansi_strcpy(tmp.ptr, "<-error: uri too long->");	tmp.slen = pj_ansi_strlen(tmp.ptr);    } else	tmp.slen = len;    /* Save the local info. */    pj_strdup(dlg->pool, &dlg->local.info_str, &tmp);    /* Calculate hash value of local tag. */    dlg->local.tag_hval = pj_hash_calc(0, dlg->local.info->tag.ptr,				       dlg->local.info->tag.slen);    /* Randomize local cseq */    dlg->local.first_cseq = pj_rand() % 0x7FFFFFFFL;    dlg->local.cseq = dlg->local.first_cseq;    /* Init local contact. */    /* TODO:     *  Section 12.1.1, paragraph about using SIPS URI in Contact.     *  If the request that initiated the dialog contained a SIPS URI      *  in the Request-URI or in the top Record-Route header field value,      *  if there was any, or the Contact header field if there was no      *  Record-Route header field, the Contact header field in the response     *  MUST be a SIPS URI.     */    if (contact) {	pj_str_t tmp;	dlg->local.contact = pjsip_contact_hdr_create(dlg->pool);	pj_strdup_with_null(dlg->pool, &tmp, contact);	dlg->local.contact->uri = pjsip_parse_uri(dlg->pool, tmp.ptr, tmp.slen,						  PJSIP_PARSE_URI_AS_NAMEADDR);	if (!dlg->local.contact->uri) {	    status = PJSIP_EINVALIDURI;	    goto on_error;	}    } else {	dlg->local.contact = pjsip_contact_hdr_create(dlg->pool);	dlg->local.contact->uri = dlg->local.info->uri;    }    /* Init remote info from the From header. */    dlg->remote.info = pjsip_hdr_clone(dlg->pool, rdata->msg_info.from);    pjsip_fromto_hdr_set_to(dlg->remote.info);    /* Print the remote info. */    len = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR,			  dlg->remote.info->uri, tmp.ptr, TMP_LEN);    if (len < 1) {	pj_ansi_strcpy(tmp.ptr, "<-error: uri too long->");	tmp.slen = pj_ansi_strlen(tmp.ptr);    } else	tmp.slen = len;    /* Save the remote info. */    pj_strdup(dlg->pool, &dlg->remote.info_str, &tmp);    /* Init remote's contact from Contact header. */    contact_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, 				     NULL);    if (!contact_hdr) {	status = PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_BAD_REQUEST);	goto on_error;    }    dlg->remote.contact = pjsip_hdr_clone(dlg->pool, contact_hdr);    /* Init remote's CSeq from CSeq header */    dlg->remote.cseq = dlg->remote.first_cseq = rdata->msg_info.cseq->cseq;    /* Set initial target to remote's Contact. */    dlg->target = dlg->remote.contact->uri;    /* Initial role is UAS */    dlg->role = PJSIP_ROLE_UAS;    /* Secure?      *  RFC 3261 Section 12.1.1:     *  If the request arrived over TLS, and the Request-URI contained a      *  SIPS URI, the 'secure' flag is set to TRUE.     */    dlg->secure = PJSIP_TRANSPORT_IS_SECURE(rdata->tp_info.transport) &&

⌨️ 快捷键说明

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