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

📄 sip_xaction.c

📁 VoIP use SIP protocol interface
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END *//* * Copyright 2006 Sun Microsystems, Inc.  All rights reserved. * Use is subject to license terms. */#pragma ident	"@(#)sip_xaction.c	1.13	06/08/16 SMI"#include "sip_miscdefs.h"#include "sip_xaction.h"#include "sip_hash.h"#include "sip_msg.h"#define	RFC_3261_BRANCH "z9hG4bK"/* The transaction hash table */sip_hash_t	sip_xaction_hash[SIP_HASH_SZ];int (*sip_xaction_ulp_trans_err)(sip_transaction_t, int, void *) = NULL;void (*sip_xaction_ulp_state_cb)(sip_transaction_t, sip_msg_t, int, int) = NULL;int sip_xaction_add(sip_xaction_t *, char *, _sip_msg_t *, sip_method_t);static boolean_t sip_is_conn_obj_cache(sip_conn_object_t, void *);/* Get the md5 hash of the required fields */intsip_find_md5_digest(char *bid, _sip_msg_t *msg, uint16_t *hindex,    sip_method_t method){	boolean_t	is_2543;	is_2543 = (bid == NULL ||	    strncmp(bid, RFC_3261_BRANCH, strlen(RFC_3261_BRANCH)) != 0);	if (is_2543 && msg == NULL)		return (EINVAL);	if (is_2543) {		_sip_header_t	*from = NULL;		_sip_header_t	*cid = NULL;		_sip_header_t	*via = NULL;		const sip_str_t	*to_uri = NULL;		int		cseq;		int		error = 0;		/*		 * Since the response might contain parameters not in the		 * request, just use the to URI.		 */		to_uri = sip_get_to_uri_str((sip_msg_t)msg, &error);		if (to_uri == NULL || error != 0)			return (EINVAL);		cseq = sip_get_callseq_num((sip_msg_t)msg, &error);		if (cseq < 0 || error != 0)			return (EINVAL);		(void) pthread_mutex_lock(&msg->sip_msg_mutex);		via = sip_search_for_header(msg, SIP_VIA, NULL);		from = sip_search_for_header(msg, SIP_FROM, NULL);		cid = sip_search_for_header(msg, SIP_CALL_ID, NULL);		(void) pthread_mutex_unlock(&msg->sip_msg_mutex);		if (via == NULL || from == NULL || cid == NULL)			return (EINVAL);		sip_md5_hash(via->sip_hdr_start,		    via->sip_hdr_end - via->sip_hdr_start,		    cid->sip_hdr_start,		    cid->sip_hdr_end - cid->sip_hdr_start,		    from->sip_hdr_start,		    from->sip_hdr_end - from->sip_hdr_start,		    (char *)&cseq, sizeof (int),		    (char *)&method, sizeof (sip_method_t),		    to_uri->sip_str_ptr, to_uri->sip_str_len,		    (uchar_t *)hindex);	} else {		sip_md5_hash(bid, strlen(bid), (char *)&method,		    sizeof (sip_method_t), NULL, 0, NULL, 0, NULL, 0, NULL, 0,		    (uchar_t *)hindex);	}	return (0);}/* Add object to the connection cache object. Not checking for duplicates!! */intsip_add_conn_obj_cache(sip_conn_object_t obj, void *cobj){	void			**obj_val;	sip_conn_obj_pvt_t	*pvt_data;	sip_conn_cache_t	*xaction_list;	sip_xaction_t		*sip_trans = (sip_xaction_t *)cobj;	/* Is already cached */	if (sip_trans->sip_xaction_conn_obj != NULL) {		if (sip_is_conn_obj_cache(sip_trans->sip_xaction_conn_obj,		    (void *)sip_trans)) {			return (0);		}		/* Transaction has cached a different conn_obj, release it */		sip_del_conn_obj_cache(sip_trans->sip_xaction_conn_obj,		    (void *)sip_trans);	}	xaction_list = malloc(sizeof (sip_conn_cache_t));	if (xaction_list == NULL)		return (ENOMEM);	xaction_list->obj = cobj;	xaction_list->next = xaction_list->prev = NULL;	obj_val = (void *)obj;	pvt_data = (sip_conn_obj_pvt_t *)*obj_val;	if (pvt_data == NULL) {		free(xaction_list);		return (EINVAL);	}	(void) pthread_mutex_lock(&pvt_data->sip_conn_obj_cache_lock);	if (pvt_data->sip_conn_obj_cache == NULL) {		pvt_data->sip_conn_obj_cache = xaction_list;	} else {		xaction_list->next =  pvt_data->sip_conn_obj_cache;		pvt_data->sip_conn_obj_cache->prev = xaction_list;		pvt_data->sip_conn_obj_cache = xaction_list;	}	sip_refhold_conn(obj);	sip_trans->sip_xaction_conn_obj = obj;	(void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_cache_lock);	return (0);}/* * Walk thru the list of transactions that have cached this obj and * and return true if 'cobj' is one of them. */static boolean_tsip_is_conn_obj_cache(sip_conn_object_t obj, void *cobj){	void			**obj_val;	sip_conn_obj_pvt_t	*pvt_data;	sip_conn_cache_t	*xaction_list;	sip_xaction_t		*trans;	sip_xaction_t		*ctrans = (sip_xaction_t *)cobj;	obj_val = (void *)obj;	pvt_data = (sip_conn_obj_pvt_t *)*obj_val;	if (pvt_data == NULL)		return (B_FALSE);	(void) pthread_mutex_lock(&pvt_data->sip_conn_obj_cache_lock);	xaction_list = pvt_data->sip_conn_obj_cache;	while (xaction_list != NULL) {		trans = (sip_xaction_t *)xaction_list->obj;		if (ctrans != trans) {			xaction_list = xaction_list->next;			continue;		}		(void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_cache_lock);		return (B_TRUE);	}	(void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_cache_lock);	return (B_FALSE);}/* * Walk thru the list of transactions that have cached this obj and * refrele the objs. */voidsip_del_conn_obj_cache(sip_conn_object_t obj, void *cobj){	void			**obj_val;	sip_conn_obj_pvt_t	*pvt_data;	sip_conn_cache_t	*xaction_list;	sip_conn_cache_t	*tmp_list;	sip_xaction_t		*trans;	sip_xaction_t		*ctrans = NULL;	if (cobj != NULL)		ctrans = (sip_xaction_t *)cobj;	obj_val = (void *)obj;	pvt_data = (sip_conn_obj_pvt_t *)*obj_val;	if (pvt_data == NULL) {	/* ASSERT FALSE if ctrans != NULL?? */		if (ctrans != NULL) {			sip_refrele_conn(obj);			ctrans->sip_xaction_conn_obj = NULL;		}		return;	}	(void) pthread_mutex_lock(&pvt_data->sip_conn_obj_cache_lock);	xaction_list = pvt_data->sip_conn_obj_cache;	while (xaction_list != NULL) {		tmp_list = xaction_list;		trans = (sip_xaction_t *)xaction_list->obj;		assert(trans != NULL);		if (ctrans != NULL && ctrans != trans) {			xaction_list = xaction_list->next;			continue;		}		if (ctrans == NULL)			(void) pthread_mutex_lock(&trans->sip_xaction_mutex);		assert(trans->sip_xaction_conn_obj == obj);		sip_refrele_conn(obj);		trans->sip_xaction_conn_obj = NULL;		if (ctrans == NULL)			(void) pthread_mutex_unlock(&trans->sip_xaction_mutex);		xaction_list = xaction_list->next;		/* Take the obj out of the list */		if (tmp_list == pvt_data->sip_conn_obj_cache) {			if (xaction_list == NULL) {				pvt_data->sip_conn_obj_cache = NULL;			} else {				xaction_list->prev = NULL;				pvt_data->sip_conn_obj_cache = xaction_list;			}		} else if (xaction_list == NULL) {			assert(tmp_list->prev != NULL);			tmp_list->prev->next = NULL;		} else {			assert(tmp_list->prev != NULL);			tmp_list->prev->next = xaction_list;			xaction_list->prev = tmp_list->prev;		}		tmp_list->prev = NULL;		tmp_list->next = NULL;		tmp_list->obj = NULL;		free(tmp_list);	}	(void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_cache_lock);}/* * Check for a transaction match. Passed to sip_hash_find(). */boolean_tsip_xaction_match(void *obj, void *hindex){	sip_xaction_t	*tmp = (sip_xaction_t *)obj;	tmp = (sip_xaction_t *)obj;	if (SIP_IS_XACTION_TERMINATED(tmp->sip_xaction_state))		return (B_FALSE);	if (bcmp(tmp->sip_xaction_hash_digest, hindex,	    sizeof (tmp->sip_xaction_hash_digest)) == 0) {		SIP_XACTION_REFCNT_INCR(tmp);		return (B_TRUE);	}	return (B_FALSE);}/* Find a transaction */static sip_xaction_t *sip_xaction_find(char *branchid, _sip_msg_t *msg, int which){	sip_xaction_t		*tmp;	uint16_t		hash_index[8];	int			hindex;	sip_method_t		method;	int			error;	sip_message_type_t	*sip_msg_info;	sip_msg_info = msg->sip_msg_req_res;	method = sip_get_callseq_method((sip_msg_t)msg, &error);	if (error != 0)		return (NULL);	/*	 * If we are getting a ACK/CANCEL we need to match with the	 * corresponding INVITE, if any.	 */	if (sip_msg_info->is_request && which == SIP_SERVER_TRANSACTION &&	    (method == ACK || method == CANCEL)) {		method = INVITE;	}	if (sip_find_md5_digest(branchid, msg, hash_index, method) != 0)		return (NULL);	hindex = SIP_DIGEST_TO_HASH(hash_index);	tmp = (sip_xaction_t *)sip_hash_find(sip_xaction_hash,	    (void *)hash_index, hindex, sip_xaction_match);	return (tmp);}

⌨️ 快捷键说明

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