40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * CDDL HEADER START
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 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * See the License for the specific language governing permissions
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * and limitations under the License.
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 * CDDL HEADER END
943efbc33954e332318b6365bf27037c05bff72cgm * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Use is subject to license terms.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi#pragma ident "%Z%%M% %I% %E% SMI"
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * The transaction hash table
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;
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 * Get the md5 hash of the required fields
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_find_md5_digest(char *bid, _sip_msg_t *msg, uint16_t *hindex,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi strncmp(bid, RFC_3261_BRANCH, strlen(RFC_3261_BRANCH)) != 0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Since the response might contain parameters not in the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * request, just use the to URI.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (char *)&cseq, sizeof (int),
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sizeof (sip_method_t), NULL, 0, NULL, 0, NULL, 0, NULL, 0,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Add object to the connection cache object. Not checking for duplicates!!
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Is already cached
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_is_conn_obj_cache(sip_trans->sip_xaction_conn_obj,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void *)sip_trans)) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Transaction has cached a different conn_obj, release it
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&pvt_data->sip_conn_obj_cache_lock);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_cache_lock);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Walk thru the list of transactions that have cached this obj and
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * and return true if 'cobj' is one of them.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&pvt_data->sip_conn_obj_cache_lock);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_cache_lock);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_cache_lock);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Walk thru the list of transactions that have cached this obj and
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * refrele the objs.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (pvt_data == NULL) { /* ASSERT FALSE if ctrans != NULL?? */
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_lock(&pvt_data->sip_conn_obj_cache_lock);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Take the obj out of the list
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_unlock(&pvt_data->sip_conn_obj_cache_lock);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Check for a transaction match. Passed to sip_hash_find().
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Find a transaction
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_xaction_find(char *branchid, _sip_msg_t *msg, int which)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * If we are getting a ACK/CANCEL we need to match with the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * corresponding INVITE, if any.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_msg_info->is_request && which == SIP_SERVER_TRANSACTION &&
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_find_md5_digest(branchid, msg, hash_index, method) != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * create a transaction.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_xaction_create(sip_conn_object_t obj, _sip_msg_t *msg, char *branchid,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Make sure we are not creating a transaction for
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * an ACK request.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi trans->sip_xaction_branch_id = (char *)sip_branchid(NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi trans->sip_xaction_branch_id = (char *)malloc(strlen(branchid)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi (void) pthread_mutex_init(&trans->sip_xaction_mutex, NULL);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (ret != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Get connection object specific timeouts, if present
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if ((ret = sip_xaction_add(trans, branchid, msg, method)) != 0) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Find a transaction, create if asked for
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_xaction_get(sip_conn_object_t obj, sip_msg_t msg, boolean_t create,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * If we are sending a request, must be conformant to RFC 3261.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_trans = sip_xaction_create(obj, _msg, branchid, error);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Delete a transaction if the reference count is 0. Passed to
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * sip_hash_delete().
943efbc33954e332318b6365bf27037c05bff72cgm sip_write_to_log((void *)tmp, SIP_TRANSACTION_LOG, NULL, 0);
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 for (count = 0; count <= SIP_SRV_NONINV_TERMINATED; count++) {
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Delete a SIP transaction
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi hindex = SIP_DIGEST_TO_HASH(trans->sip_xaction_hash_digest);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi sip_hash_delete(sip_xaction_hash, trans->sip_xaction_hash_digest,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Add a SIP transaction into the hash list.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331visip_xaction_add(sip_xaction_t *trans, char *branchid, _sip_msg_t *msg,
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi if (sip_find_md5_digest(branchid, msg, hash_index, method) != 0)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * trans is not in the list as yet, so no need to hold the lock
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi bcopy(hash_index, trans->sip_xaction_hash_digest, sizeof (hash_index));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return (0);
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Given a state, return the string - This is mostly for debug purposes
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi switch (state) {
943efbc33954e332318b6365bf27037c05bff72cgm return ("SIP_NEW_TRANSACTION");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_CLNT_CALLING");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_CLNT_INV_PROCEEDING");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_CLNT_INV_TERMINATED");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_CLNT_INV_COMPLETED");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_CLNT_TRYING");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_CLNT_NONINV_PROCEEDING");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_CLNT_NONINV_TERMINATED");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_CLNT_NONINV_COMPLETED");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_SRV_INV_PROCEEDING");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_SRV_INV_COMPLETED");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_SRV_CONFIRMED");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_SRV_INV_TERMINATED");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_SRV_TRYING");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_SRV_NONINV_PROCEEDING");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_SRV_NONINV_COMPLETED");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi return ("SIP_SRV_NONINV_TERMINATED");
943efbc33954e332318b6365bf27037c05bff72cgm return ("UNKNOWN");
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Initialize the hash table etc.
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))