40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * CDDL HEADER START
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The contents of this file are subject to the terms of the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Common Development and Distribution License (the "License").
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * You may not use this file except in compliance with the License.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * or http://www.opensolaris.org/os/licensing.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * See the License for the specific language governing permissions
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * and limitations under the License.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * When distributing Covered Code, include this CDDL HEADER in each
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * If applicable, add the following below this CDDL HEADER, with the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * fields enclosed by brackets "[]" replaced with your own identifying
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * information: Portions Copyright [yyyy] [name of copyright owner]
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * CDDL HEADER END
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
943efbc33954e332318b6365bf27037c05bff72cgm * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Use is subject to license terms.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#pragma ident "%Z%%M% %I% %E% SMI"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
2c2c41837e330b002c4220a39638150db504fe0evi#include <stdlib.h>
2c2c41837e330b002c4220a39638150db504fe0evi#include <assert.h>
2c2c41837e330b002c4220a39638150db504fe0evi#include <errno.h>
2c2c41837e330b002c4220a39638150db504fe0evi#include <pthread.h>
2c2c41837e330b002c4220a39638150db504fe0evi#include <strings.h>
2c2c41837e330b002c4220a39638150db504fe0evi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#include "sip_parse_uri.h"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#include "sip_msg.h"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#include "sip_miscdefs.h"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#include "sip_xaction.h"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#include "sip_hash.h"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#define RFC_3261_BRANCH "z9hG4bK"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The transaction hash table
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_hash_t sip_xaction_hash[SIP_HASH_SZ];
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viint (*sip_xaction_ulp_trans_err)(sip_transaction_t, int, void *) = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid (*sip_xaction_ulp_state_cb)(sip_transaction_t, sip_msg_t, int, int) = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viint sip_xaction_add(sip_xaction_t *, char *, _sip_msg_t *, sip_method_t);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vistatic boolean_t sip_is_conn_obj_cache(sip_conn_object_t, void *);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Get the md5 hash of the required fields
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viint
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_find_md5_digest(char *bid, _sip_msg_t *msg, uint16_t *hindex,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_method_t method)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi boolean_t is_2543;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi is_2543 = (bid == NULL ||
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi strncmp(bid, RFC_3261_BRANCH, strlen(RFC_3261_BRANCH)) != 0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (is_2543 && msg == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (is_2543) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_header_t *from = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_header_t *cid = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_header_t *via = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi const sip_str_t *to_uri = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int cseq;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int error = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Since the response might contain parameters not in the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * request, just use the to URI.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi to_uri = sip_get_to_uri_str((sip_msg_t)msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (to_uri == NULL || error != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi cseq = sip_get_callseq_num((sip_msg_t)msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (cseq < 0 || error != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi via = sip_search_for_header(msg, SIP_VIA, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi from = sip_search_for_header(msg, SIP_FROM, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi cid = sip_search_for_header(msg, SIP_CALL_ID, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&msg->sip_msg_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (via == NULL || from == NULL || cid == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_md5_hash(via->sip_hdr_start,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi via->sip_hdr_end - via->sip_hdr_start,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi cid->sip_hdr_start,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi cid->sip_hdr_end - cid->sip_hdr_start,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi from->sip_hdr_start,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi from->sip_hdr_end - from->sip_hdr_start,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (char *)&cseq, sizeof (int),
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (char *)&method, sizeof (sip_method_t),
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi to_uri->sip_str_ptr, to_uri->sip_str_len,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (uchar_t *)hindex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_md5_hash(bid, strlen(bid), (char *)&method,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sizeof (sip_method_t), NULL, 0, NULL, 0, NULL, 0, NULL, 0,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (uchar_t *)hindex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Add object to the connection cache object. Not checking for duplicates!!
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viint
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_add_conn_obj_cache(sip_conn_object_t obj, void *cobj)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi void **obj_val;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_conn_obj_pvt_t *pvt_data;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_conn_cache_t *xaction_list;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_xaction_t *sip_trans = (sip_xaction_t *)cobj;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Is already cached
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_trans->sip_xaction_conn_obj != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_is_conn_obj_cache(sip_trans->sip_xaction_conn_obj,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void *)sip_trans)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Transaction has cached a different conn_obj, release it
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_del_conn_obj_cache(sip_trans->sip_xaction_conn_obj,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void *)sip_trans);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi xaction_list = malloc(sizeof (sip_conn_cache_t));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (xaction_list == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ENOMEM);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi xaction_list->obj = cobj;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi xaction_list->next = xaction_list->prev = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi obj_val = (void *)obj;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi pvt_data = (sip_conn_obj_pvt_t *)*obj_val;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (pvt_data == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(xaction_list);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&pvt_data->sip_conn_obj_cache_lock);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (pvt_data->sip_conn_obj_cache == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi pvt_data->sip_conn_obj_cache = xaction_list;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi xaction_list->next = pvt_data->sip_conn_obj_cache;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi pvt_data->sip_conn_obj_cache->prev = xaction_list;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi pvt_data->sip_conn_obj_cache = xaction_list;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_refhold_conn(obj);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_trans->sip_xaction_conn_obj = obj;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_cache_lock);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Walk thru the list of transactions that have cached this obj and
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * and return true if 'cobj' is one of them.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vistatic boolean_t
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_is_conn_obj_cache(sip_conn_object_t obj, void *cobj)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi void **obj_val;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_conn_obj_pvt_t *pvt_data;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_conn_cache_t *xaction_list;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_xaction_t *trans;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_xaction_t *ctrans = (sip_xaction_t *)cobj;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi obj_val = (void *)obj;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi pvt_data = (sip_conn_obj_pvt_t *)*obj_val;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (pvt_data == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_FALSE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&pvt_data->sip_conn_obj_cache_lock);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi xaction_list = pvt_data->sip_conn_obj_cache;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (xaction_list != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi trans = (sip_xaction_t *)xaction_list->obj;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ctrans != trans) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi xaction_list = xaction_list->next;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi continue;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_cache_lock);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_TRUE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_cache_lock);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_FALSE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Walk thru the list of transactions that have cached this obj and
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * refrele the objs.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_del_conn_obj_cache(sip_conn_object_t obj, void *cobj)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi void **obj_val;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_conn_obj_pvt_t *pvt_data;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_conn_cache_t *xaction_list;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_conn_cache_t *tmp_list;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_xaction_t *trans;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_xaction_t *ctrans = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (cobj != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi ctrans = (sip_xaction_t *)cobj;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi obj_val = (void *)obj;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi pvt_data = (sip_conn_obj_pvt_t *)*obj_val;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (pvt_data == NULL) { /* ASSERT FALSE if ctrans != NULL?? */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ctrans != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_refrele_conn(obj);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi ctrans->sip_xaction_conn_obj = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&pvt_data->sip_conn_obj_cache_lock);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi xaction_list = pvt_data->sip_conn_obj_cache;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi while (xaction_list != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tmp_list = xaction_list;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi trans = (sip_xaction_t *)xaction_list->obj;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(trans != NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ctrans != NULL && ctrans != trans) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi xaction_list = xaction_list->next;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi continue;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ctrans == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&trans->sip_xaction_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(trans->sip_xaction_conn_obj == obj);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_refrele_conn(obj);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi trans->sip_xaction_conn_obj = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ctrans == NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&trans->sip_xaction_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi xaction_list = xaction_list->next;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Take the obj out of the list
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (tmp_list == pvt_data->sip_conn_obj_cache) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (xaction_list == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi pvt_data->sip_conn_obj_cache = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi xaction_list->prev = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi pvt_data->sip_conn_obj_cache = xaction_list;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else if (xaction_list == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(tmp_list->prev != NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tmp_list->prev->next = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(tmp_list->prev != NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tmp_list->prev->next = xaction_list;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi xaction_list->prev = tmp_list->prev;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tmp_list->prev = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tmp_list->next = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tmp_list->obj = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(tmp_list);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_cache_lock);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Check for a transaction match. Passed to sip_hash_find().
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viboolean_t
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_xaction_match(void *obj, void *hindex)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_xaction_t *tmp = (sip_xaction_t *)obj;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tmp = (sip_xaction_t *)obj;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (SIP_IS_XACTION_TERMINATED(tmp->sip_xaction_state))
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_FALSE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (bcmp(tmp->sip_xaction_hash_digest, hindex,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sizeof (tmp->sip_xaction_hash_digest)) == 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_XACTION_REFCNT_INCR(tmp);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_TRUE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_FALSE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Find a transaction
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vistatic sip_xaction_t *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_xaction_find(char *branchid, _sip_msg_t *msg, int which)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_xaction_t *tmp;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi uint16_t hash_index[8];
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int hindex;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_method_t method;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int error;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_message_type_t *sip_msg_info;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_msg_info = msg->sip_msg_req_res;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi method = sip_get_callseq_method((sip_msg_t)msg, &error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * If we are getting a ACK/CANCEL we need to match with the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * corresponding INVITE, if any.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_msg_info->is_request && which == SIP_SERVER_TRANSACTION &&
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (method == ACK || method == CANCEL)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi method = INVITE;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_find_md5_digest(branchid, msg, hash_index, method) != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi hindex = SIP_DIGEST_TO_HASH(hash_index);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tmp = (sip_xaction_t *)sip_hash_find(sip_xaction_hash,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void *)hash_index, hindex, sip_xaction_match);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (tmp);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * create a transaction.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vistatic sip_xaction_t *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_xaction_create(sip_conn_object_t obj, _sip_msg_t *msg, char *branchid,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int *error)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_xaction_t *trans;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_message_type_t *sip_msg_info;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int state = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int prev_state = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_method_t method;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int ret;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int timer1 = sip_timer_T1;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int timer4 = sip_timer_T4;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int timerd = sip_timer_TD;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *error = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Make sure we are not creating a transaction for
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * an ACK request.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi trans = (sip_xaction_t *)malloc(sizeof (sip_xaction_t));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (trans == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *error = ENOMEM;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi bzero(trans, sizeof (sip_xaction_t));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (branchid == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi trans->sip_xaction_branch_id = (char *)sip_branchid(NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (trans->sip_xaction_branch_id == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(trans);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *error = ENOMEM;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi trans->sip_xaction_branch_id = (char *)malloc(strlen(branchid)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi + 1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (trans->sip_xaction_branch_id == NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(trans);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *error = ENOMEM;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) strncpy(trans->sip_xaction_branch_id, branchid,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi strlen(branchid));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi trans->sip_xaction_branch_id[strlen(branchid)] = '\0';
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_init(&trans->sip_xaction_mutex, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_MSG_REFCNT_INCR(msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi trans->sip_xaction_orig_msg = msg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi assert(msg->sip_msg_req_res != NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_msg_info = msg->sip_msg_req_res;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_msg_info->is_request) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi method = sip_msg_info->sip_req_method;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi } else {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi method = sip_get_callseq_method((sip_msg_t)msg, &ret);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ret != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(trans->sip_xaction_branch_id);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(trans);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *error = ret;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (method == INVITE)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi state = SIP_SRV_INV_PROCEEDING;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi else
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi state = SIP_SRV_TRYING;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi trans->sip_xaction_method = method;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi trans->sip_xaction_state = state;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Get connection object specific timeouts, if present
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_conn_timer1 != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi timer1 = sip_conn_timer1(obj);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_conn_timer4 != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi timer4 = sip_conn_timer4(obj);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_conn_timerd != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi timerd = sip_conn_timerd(obj);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_INIT_TIMER(trans->sip_xaction_TA, 2 * timer1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_INIT_TIMER(trans->sip_xaction_TB, 64 * timer1)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_INIT_TIMER(trans->sip_xaction_TD, timerd);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_INIT_TIMER(trans->sip_xaction_TE, timer1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_INIT_TIMER(trans->sip_xaction_TF, 64 * timer1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_INIT_TIMER(trans->sip_xaction_TG, 2 * timer1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_INIT_TIMER(trans->sip_xaction_TH, 64 * timer1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_INIT_TIMER(trans->sip_xaction_TI, timer4);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_INIT_TIMER(trans->sip_xaction_TJ, 64 * timer1);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_INIT_TIMER(trans->sip_xaction_TK, timer4);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = sip_xaction_add(trans, branchid, msg, method)) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_destroy(&trans->sip_xaction_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(trans->sip_xaction_branch_id);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(trans);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *error = ret;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_xaction_ulp_state_cb != NULL &&
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi prev_state != trans->sip_xaction_state) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_xaction_ulp_state_cb((sip_transaction_t)trans,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (sip_msg_t)msg, prev_state, trans->sip_xaction_state);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (trans);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Find a transaction, create if asked for
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_xaction_t *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_xaction_get(sip_conn_object_t obj, sip_msg_t msg, boolean_t create,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int which, int *error)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi char *branchid;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_xaction_t *sip_trans;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _sip_msg_t *_msg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_message_type_t *sip_msg_info;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *error = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi _msg = (_sip_msg_t *)msg;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_msg_info = ((_sip_msg_t *)msg)->sip_msg_req_res;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi branchid = sip_get_branchid(msg, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_trans = sip_xaction_find(branchid, _msg, which);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_trans == NULL && create) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * If we are sending a request, must be conformant to RFC 3261.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_msg_info->is_request &&
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (branchid == NULL || strncmp(branchid,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi RFC_3261_BRANCH, strlen(RFC_3261_BRANCH) != 0))) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (error != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *error = EINVAL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (branchid != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(branchid);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_trans = sip_xaction_create(obj, _msg, branchid, error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_trans != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_XACTION_REFCNT_INCR(sip_trans);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (branchid != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(branchid);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (sip_trans);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Delete a transaction if the reference count is 0. Passed to
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * sip_hash_delete().
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viboolean_t
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_xaction_remove(void *obj, void *hindex, int *found)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_xaction_t *tmp = (sip_xaction_t *)obj;
943efbc33954e332318b6365bf27037c05bff72cgm int count = 0;
943efbc33954e332318b6365bf27037c05bff72cgm sip_msg_chain_t *msg_chain;
943efbc33954e332318b6365bf27037c05bff72cgm sip_msg_chain_t *nmsg_chain;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *found = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tmp = (sip_xaction_t *)obj;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&tmp->sip_xaction_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (bcmp(tmp->sip_xaction_hash_digest, hindex,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sizeof (tmp->sip_xaction_hash_digest)) == 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi *found = 1;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (tmp->sip_xaction_ref_cnt != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&tmp->sip_xaction_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_FALSE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_destroy(&tmp->sip_xaction_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_CANCEL_TIMER(tmp->sip_xaction_TA);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_CANCEL_TIMER(tmp->sip_xaction_TB);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_CANCEL_TIMER(tmp->sip_xaction_TD);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_CANCEL_TIMER(tmp->sip_xaction_TE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_CANCEL_TIMER(tmp->sip_xaction_TF);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_CANCEL_TIMER(tmp->sip_xaction_TG);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_CANCEL_TIMER(tmp->sip_xaction_TH);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_CANCEL_TIMER(tmp->sip_xaction_TI);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_CANCEL_TIMER(tmp->sip_xaction_TJ);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_CANCEL_TIMER(tmp->sip_xaction_TK);
943efbc33954e332318b6365bf27037c05bff72cgm sip_write_to_log((void *)tmp, SIP_TRANSACTION_LOG, NULL, 0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(tmp->sip_xaction_branch_id);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (tmp->sip_xaction_last_msg != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_MSG_REFCNT_DECR(tmp->sip_xaction_last_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tmp->sip_xaction_last_msg = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (tmp->sip_xaction_orig_msg != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_MSG_REFCNT_DECR(tmp->sip_xaction_orig_msg);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi tmp->sip_xaction_orig_msg = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (tmp->sip_xaction_conn_obj != NULL) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_del_conn_obj_cache(tmp->sip_xaction_conn_obj,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void *)tmp);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
943efbc33954e332318b6365bf27037c05bff72cgm /*
943efbc33954e332318b6365bf27037c05bff72cgm * If the transaction logging is disabled before we could
943efbc33954e332318b6365bf27037c05bff72cgm * write the captured messages into the transaction log, then
943efbc33954e332318b6365bf27037c05bff72cgm * we need to free those captured messsages
943efbc33954e332318b6365bf27037c05bff72cgm */
943efbc33954e332318b6365bf27037c05bff72cgm for (count = 0; count <= SIP_SRV_NONINV_TERMINATED; count++) {
943efbc33954e332318b6365bf27037c05bff72cgm msg_chain = tmp->sip_xaction_log[count].sip_msgs;
943efbc33954e332318b6365bf27037c05bff72cgm while (msg_chain != NULL) {
943efbc33954e332318b6365bf27037c05bff72cgm nmsg_chain = msg_chain->next;
943efbc33954e332318b6365bf27037c05bff72cgm if (msg_chain->sip_msg != NULL)
943efbc33954e332318b6365bf27037c05bff72cgm free(msg_chain->sip_msg);
943efbc33954e332318b6365bf27037c05bff72cgm free(msg_chain);
943efbc33954e332318b6365bf27037c05bff72cgm msg_chain = nmsg_chain;
943efbc33954e332318b6365bf27037c05bff72cgm }
943efbc33954e332318b6365bf27037c05bff72cgm }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi free(tmp);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_TRUE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&tmp->sip_xaction_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (B_FALSE);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Delete a SIP transaction
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_xaction_delete(sip_xaction_t *trans)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int hindex;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&trans->sip_xaction_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi hindex = SIP_DIGEST_TO_HASH(trans->sip_xaction_hash_digest);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (trans->sip_xaction_ref_cnt != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&trans->sip_xaction_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&trans->sip_xaction_mutex);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_hash_delete(sip_xaction_hash, trans->sip_xaction_hash_digest,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi hindex, sip_xaction_remove);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Add a SIP transaction into the hash list.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viint
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_xaction_add(sip_xaction_t *trans, char *branchid, _sip_msg_t *msg,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_method_t method)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi uint16_t hash_index[8];
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_find_md5_digest(branchid, msg, hash_index, method) != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (EINVAL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi /*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * trans is not in the list as yet, so no need to hold the lock
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi bcopy(hash_index, trans->sip_xaction_hash_digest, sizeof (hash_index));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_hash_add(sip_xaction_hash, (void *)trans,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi SIP_DIGEST_TO_HASH(hash_index)) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (ENOMEM);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Given a state, return the string - This is mostly for debug purposes
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vichar *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_get_xaction_state(int state)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi switch (state) {
943efbc33954e332318b6365bf27037c05bff72cgm case SIP_NEW_TRANSACTION:
943efbc33954e332318b6365bf27037c05bff72cgm return ("SIP_NEW_TRANSACTION");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi case SIP_CLNT_CALLING:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_CLNT_CALLING");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi case SIP_CLNT_INV_PROCEEDING:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_CLNT_INV_PROCEEDING");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi case SIP_CLNT_INV_TERMINATED:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_CLNT_INV_TERMINATED");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi case SIP_CLNT_INV_COMPLETED:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_CLNT_INV_COMPLETED");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi case SIP_CLNT_TRYING:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_CLNT_TRYING");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi case SIP_CLNT_NONINV_PROCEEDING:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_CLNT_NONINV_PROCEEDING");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi case SIP_CLNT_NONINV_TERMINATED:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_CLNT_NONINV_TERMINATED");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi case SIP_CLNT_NONINV_COMPLETED:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_CLNT_NONINV_COMPLETED");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi case SIP_SRV_INV_PROCEEDING:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_SRV_INV_PROCEEDING");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi case SIP_SRV_INV_COMPLETED:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_SRV_INV_COMPLETED");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi case SIP_SRV_CONFIRMED:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_SRV_CONFIRMED");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi case SIP_SRV_INV_TERMINATED:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_SRV_INV_TERMINATED");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi case SIP_SRV_TRYING:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_SRV_TRYING");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi case SIP_SRV_NONINV_PROCEEDING:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_SRV_NONINV_PROCEEDING");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi case SIP_SRV_NONINV_COMPLETED:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_SRV_NONINV_COMPLETED");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi case SIP_SRV_NONINV_TERMINATED:
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_SRV_NONINV_TERMINATED");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi default :
943efbc33954e332318b6365bf27037c05bff72cgm return ("UNKNOWN");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Initialize the hash table etc.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vivoid
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_xaction_init(int (*ulp_trans_err)(sip_transaction_t, int, void *),
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi void (*ulp_state_cb)(sip_transaction_t, sip_msg_t, int, int))
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi{
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi int cnt;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi for (cnt = 0; cnt < SIP_HASH_SZ; cnt++) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_xaction_hash[cnt].hash_count = 0;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_xaction_hash[cnt].hash_head = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_xaction_hash[cnt].hash_tail = NULL;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_init(
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi &sip_xaction_hash[cnt].sip_hash_mutex, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi }
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ulp_trans_err != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_xaction_ulp_trans_err = ulp_trans_err;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ulp_state_cb != NULL)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_xaction_ulp_state_cb = ulp_state_cb;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi}