📄 sip_xaction.c
字号:
/* * 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 + -