xref: /onnv-gate/usr/src/lib/libsip/common/sip_xaction_state_mc.c (revision 5842:e93f793783f6)
12882Svi117747 /*
22882Svi117747  * CDDL HEADER START
32882Svi117747  *
42882Svi117747  * The contents of this file are subject to the terms of the
52882Svi117747  * Common Development and Distribution License (the "License").
62882Svi117747  * You may not use this file except in compliance with the License.
72882Svi117747  *
82882Svi117747  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92882Svi117747  * or http://www.opensolaris.org/os/licensing.
102882Svi117747  * See the License for the specific language governing permissions
112882Svi117747  * and limitations under the License.
122882Svi117747  *
132882Svi117747  * When distributing Covered Code, include this CDDL HEADER in each
142882Svi117747  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152882Svi117747  * If applicable, add the following below this CDDL HEADER, with the
162882Svi117747  * fields enclosed by brackets "[]" replaced with your own identifying
172882Svi117747  * information: Portions Copyright [yyyy] [name of copyright owner]
182882Svi117747  *
192882Svi117747  * CDDL HEADER END
202882Svi117747  */
212882Svi117747 
222882Svi117747 /*
23*5842Sgm209912  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
242882Svi117747  * Use is subject to license terms.
252882Svi117747  */
262882Svi117747 
272882Svi117747 #pragma ident	"%Z%%M%	%I%	%E% SMI"
282882Svi117747 
292882Svi117747 /*
302882Svi117747  * SIP Client/Server Invite/Non-Invite Transaction State machine.
312882Svi117747  */
322882Svi117747 
333439Svi117747 #include <stdlib.h>
343439Svi117747 #include <string.h>
353439Svi117747 #include <assert.h>
363439Svi117747 #include <errno.h>
373439Svi117747 #include <pthread.h>
383439Svi117747 #include <sip.h>
393439Svi117747 
402882Svi117747 #include "sip_miscdefs.h"
413439Svi117747 #include "sip_msg.h"
422882Svi117747 #include "sip_xaction.h"
432882Svi117747 
442882Svi117747 /*
452882Svi117747  * Some Timer related info from RFC 3261, page 265.
462882Svi117747  *
472882Svi117747  * ----------------------------------------------------------------------
482882Svi117747  * Timer    Value            Section               Meaning
492882Svi117747  * ----------------------------------------------------------------------
502882Svi117747  * T1       500ms default    Section 17.1.1.1     RTT Estimate
512882Svi117747  * T2       4s               Section 17.1.2.2     The maximum retransmit
522882Svi117747  *                                                interval for non-INVITE
532882Svi117747  *                                                requests and INVITE
542882Svi117747  *                                                responses
552882Svi117747  * T4       5s               Section 17.1.2.2     Maximum duration a
562882Svi117747  *                                                message will
572882Svi117747  *                                                remain in the network
582882Svi117747  * ----------------------------------------------------------------------
592882Svi117747  * Timer A  initially T1     Section 17.1.1.2     INVITE request retransmit
602882Svi117747  *                                                interval, for UDP only
612882Svi117747  * Timer B  64*T1            Section 17.1.1.2     INVITE transaction
622882Svi117747  *                                                timeout timer
632882Svi117747  * Timer C  > 3min           Section 16.6         proxy INVITE transaction
642882Svi117747  *                            bullet 11            timeout
652882Svi117747  * Timer D  > 32s for UDP    Section 17.1.1.2     Wait time for response
662882Svi117747  *          0s for TCP/SCTP                       retransmits
672882Svi117747  * Timer E  initially T1     Section 17.1.2.2     non-INVITE request
682882Svi117747  *                                                retransmit interval,
692882Svi117747  *                                                UDP only
702882Svi117747  * Timer F  64*T1            Section 17.1.2.2     non-INVITE transaction
712882Svi117747  *                                                timeout timer
722882Svi117747  * Timer G  initially T1     Section 17.2.1       INVITE response
732882Svi117747  *                                                retransmit interval
742882Svi117747  * Timer H  64*T1            Section 17.2.1       Wait time for
752882Svi117747  *                                                ACK receipt
762882Svi117747  * Timer I  T4 for UDP       Section 17.2.1       Wait time for
772882Svi117747  *          0s for TCP/SCTP                       ACK retransmits
782882Svi117747  * Timer J  64*T1 for UDP    Section 17.2.2       Wait time for
792882Svi117747  *          0s for TCP/SCTP                       non-INVITE request
802882Svi117747  *                                                retransmits
812882Svi117747  * Timer K  T4 for UDP       Section 17.1.2.2     Wait time for
822882Svi117747  *          0s for TCP/SCTP                       response retransmits
832882Svi117747  * ----------------------------------------------------------------------
842882Svi117747  */
852882Svi117747 
862882Svi117747 #ifndef MIN
872882Svi117747 #define	MIN(a, b)	(((a) < (b)) ? (a):(b))
882882Svi117747 #endif
892882Svi117747 
902882Svi117747 /*
912882Svi117747  * Arg to the timer fire routine
922882Svi117747  */
932882Svi117747 typedef	struct sip_xaction_timer_obj_s {
942882Svi117747 	sip_xaction_timer_type_t	sip_xaction_timer_type;
952882Svi117747 	sip_xaction_t			*sip_trans;
962882Svi117747 	int				sip_xaction_timer_xport;
972882Svi117747 } sip_xaction_time_obj_t;
982882Svi117747 
992882Svi117747 int		sip_xaction_output(sip_conn_object_t, sip_xaction_t *,
1002882Svi117747 		    _sip_msg_t *);
1012882Svi117747 int		sip_xaction_input(sip_conn_object_t, sip_xaction_t *,
1022882Svi117747 		    _sip_msg_t **);
1032882Svi117747 void		sip_xaction_terminate(sip_xaction_t *, _sip_msg_t *, int);
1042882Svi117747 
1052882Svi117747 static int 	sip_clnt_xaction_output(sip_conn_object_t, sip_xaction_t *,
1062882Svi117747 		    _sip_msg_t *);
1072882Svi117747 static int	sip_clnt_xaction_input(sip_conn_object_t, sip_xaction_t *,
1082882Svi117747 		    _sip_msg_t **);
1092882Svi117747 static int	sip_clnt_xaction_inv_res(sip_conn_object_t, sip_xaction_t *,
1102882Svi117747 		    _sip_msg_t **);
1112882Svi117747 static int	sip_clnt_xaction_noninv_res(sip_conn_object_t, sip_xaction_t *,
1122882Svi117747 		    _sip_msg_t **);
1132882Svi117747 static int 	sip_srv_xaction_output(sip_conn_object_t, sip_xaction_t *,
1142882Svi117747 		    _sip_msg_t *);
1152882Svi117747 static int	sip_srv_xaction_input(sip_conn_object_t, sip_xaction_t *,
1162882Svi117747 		    _sip_msg_t **);
1172882Svi117747 static int	sip_srv_xaction_inv_res(sip_conn_object_t, sip_xaction_t *,
1182882Svi117747 		    _sip_msg_t *);
1192882Svi117747 static int	sip_srv_xaction_noninv_res(sip_conn_object_t, sip_xaction_t *,
1202882Svi117747 		    _sip_msg_t *);
1212882Svi117747 static int	sip_create_send_nonOKack(sip_conn_object_t, sip_xaction_t *,
1222882Svi117747 		    _sip_msg_t *, boolean_t);
1232882Svi117747 void		sip_xaction_state_timer_fire(void *);
1242882Svi117747 
1252882Svi117747 static sip_xaction_time_obj_t	*sip_setup_timer(sip_conn_object_t,
1262882Svi117747 				    sip_xaction_t *, _sip_msg_t *,
1272882Svi117747 				    sip_timer_t, int);
1282882Svi117747 
1292882Svi117747 /*
1302882Svi117747  * Return a timer object
1312882Svi117747  */
1322882Svi117747 static sip_xaction_time_obj_t *
sip_setup_timer(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t * sip_msg,sip_timer_t timer,int type)1332882Svi117747 sip_setup_timer(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
1342882Svi117747     _sip_msg_t *sip_msg, sip_timer_t timer, int type)
1352882Svi117747 {
1362882Svi117747 	sip_xaction_time_obj_t	*sip_timer_obj = NULL;
1372882Svi117747 
1382882Svi117747 	sip_timer_obj = (sip_xaction_time_obj_t *)
1392882Svi117747 	    malloc(sizeof (sip_xaction_time_obj_t));
1402882Svi117747 	if (sip_timer_obj == NULL)
1412882Svi117747 		return (NULL);
1422882Svi117747 	if (SIP_IS_TIMER_RUNNING(timer))
1432882Svi117747 		SIP_CANCEL_TIMER(timer);
1442882Svi117747 	sip_timer_obj->sip_xaction_timer_type = type;
1452882Svi117747 	sip_timer_obj->sip_xaction_timer_xport = sip_conn_transport(conn_obj);
1462882Svi117747 	sip_timer_obj->sip_trans = sip_trans;
1472882Svi117747 	/*
1482882Svi117747 	 * Save the message
1492882Svi117747 	 */
1502882Svi117747 	if (sip_msg != NULL) {
1512882Svi117747 		(void) sip_add_conn_obj_cache(conn_obj, (void *)sip_trans);
1522882Svi117747 		if (sip_trans->sip_xaction_last_msg != NULL) {
1532882Svi117747 			SIP_MSG_REFCNT_DECR(sip_trans->sip_xaction_last_msg);
1542882Svi117747 			sip_trans->sip_xaction_last_msg = NULL;
1552882Svi117747 		}
1562882Svi117747 		SIP_MSG_REFCNT_INCR(sip_msg);
1572882Svi117747 		sip_trans->sip_xaction_last_msg = sip_msg;
1582882Svi117747 	}
1592882Svi117747 	return (sip_timer_obj);
1602882Svi117747 }
1612882Svi117747 
1622882Svi117747 /*
1632882Svi117747  * --------------------------- Output Routines ---------------------------
1642882Svi117747  */
1652882Svi117747 
1662882Svi117747 /*
1672882Svi117747  * Send a SIP message, request or response, out
1682882Svi117747  */
1692882Svi117747 int
sip_xaction_output(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t * msg)1702882Svi117747 sip_xaction_output(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
1712882Svi117747     _sip_msg_t *msg)
1722882Svi117747 {
1732882Svi117747 	sip_message_type_t	*sip_msg_info;
1742882Svi117747 	int			ret;
1752882Svi117747 
176*5842Sgm209912 	if (conn_obj == NULL) {
177*5842Sgm209912 		(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
178*5842Sgm209912 		sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
179*5842Sgm209912 		    SIP_ASSERT_ERROR, __FILE__, __LINE__);
180*5842Sgm209912 		(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
181*5842Sgm209912 	}
1822882Svi117747 	assert(conn_obj != NULL);
1832882Svi117747 	sip_msg_info = msg->sip_msg_req_res;
1842882Svi117747 
185*5842Sgm209912 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
186*5842Sgm209912 	sip_trans->sip_xaction_msgcnt++;
187*5842Sgm209912 	sip_add_log(&sip_trans->sip_xaction_log[sip_trans->sip_xaction_state],
188*5842Sgm209912 	    (sip_msg_t)msg, sip_trans->sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
189*5842Sgm209912 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
190*5842Sgm209912 
1912882Svi117747 	if (sip_msg_info->is_request)
1922882Svi117747 		return (sip_clnt_xaction_output(conn_obj, sip_trans, msg));
1932882Svi117747 
1942882Svi117747 	ret = sip_srv_xaction_output(conn_obj, sip_trans, msg);
1952882Svi117747 
1962882Svi117747 	return (ret);
1972882Svi117747 }
1982882Svi117747 
1992882Svi117747 /*
2002882Svi117747  * Send a Request out
2012882Svi117747  */
2022882Svi117747 static int
sip_clnt_xaction_output(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t * msg)2032882Svi117747 sip_clnt_xaction_output(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
2042882Svi117747     _sip_msg_t *msg)
2052882Svi117747 {
2062882Svi117747 	sip_xaction_time_obj_t	*timer_obj_A = NULL;
2072882Svi117747 	sip_xaction_time_obj_t	*timer_obj_B = NULL;
2082882Svi117747 	sip_xaction_time_obj_t	*timer_obj_E = NULL;
2092882Svi117747 	sip_xaction_time_obj_t	*timer_obj_F = NULL;
2102882Svi117747 	sip_message_type_t	*sip_msg_info;
2112882Svi117747 	int			prev_state;
2122882Svi117747 	int			error = 0;
2132882Svi117747 	boolean_t		isreliable;
2142882Svi117747 
2152882Svi117747 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
2162882Svi117747 	prev_state = sip_trans->sip_xaction_state;
217*5842Sgm209912 	if (msg->sip_msg_req_res == NULL) {
218*5842Sgm209912 		sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
219*5842Sgm209912 		    SIP_ASSERT_ERROR, __FILE__, __LINE__);
220*5842Sgm209912 	}
2212882Svi117747 	assert(msg->sip_msg_req_res != NULL);
2222882Svi117747 	sip_msg_info = msg->sip_msg_req_res;
2232882Svi117747 	isreliable = sip_is_conn_reliable(conn_obj);
2242882Svi117747 
2252882Svi117747 	if (sip_msg_info->sip_req_method == INVITE) {
2262882Svi117747 		/*
2272882Svi117747 		 * if transport is not reliable, start TIMER A.
2282882Svi117747 		 */
2292882Svi117747 		if (!isreliable) {
2302882Svi117747 			timer_obj_A = sip_setup_timer(conn_obj, sip_trans,
2312882Svi117747 			    msg, sip_trans->sip_xaction_TA,
2322882Svi117747 			    SIP_XACTION_TIMER_A);
2332882Svi117747 			if (timer_obj_A == NULL) {
2342882Svi117747 				error = ENOMEM;
2352882Svi117747 				goto error_ret;
2362882Svi117747 			}
2372882Svi117747 		}
2382882Svi117747 
2392882Svi117747 		timer_obj_B = sip_setup_timer(conn_obj, sip_trans, NULL,
2402882Svi117747 		    sip_trans->sip_xaction_TB, SIP_XACTION_TIMER_B);
2412882Svi117747 		if (timer_obj_B == NULL) {
2422882Svi117747 			error = ENOMEM;
2432882Svi117747 			goto error_ret;
2442882Svi117747 		}
2452882Svi117747 		if (timer_obj_A != NULL) {
2462882Svi117747 			SIP_SCHED_TIMER(sip_trans->sip_xaction_TA, timer_obj_A,
2472882Svi117747 			    sip_xaction_state_timer_fire);
2482882Svi117747 			if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TA)) {
2492882Svi117747 				error = ENOMEM;
2502882Svi117747 				goto error_ret;
2512882Svi117747 			}
2522882Svi117747 		}
2532882Svi117747 		SIP_SCHED_TIMER(sip_trans->sip_xaction_TB, timer_obj_B,
2542882Svi117747 		    sip_xaction_state_timer_fire);
2552882Svi117747 		if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TB)) {
2562882Svi117747 			if (timer_obj_A != NULL)
2572882Svi117747 				SIP_CANCEL_TIMER(sip_trans->sip_xaction_TA)
2582882Svi117747 			error = ENOMEM;
2592882Svi117747 			goto error_ret;
2602882Svi117747 		}
2612882Svi117747 		sip_trans->sip_xaction_state = SIP_CLNT_CALLING;
2622882Svi117747 	} else {
2632882Svi117747 		/*
2642882Svi117747 		 * if transport is not reliable, start rexmit Timer E.
2652882Svi117747 		 */
2662882Svi117747 		if (!isreliable) {
2672882Svi117747 			timer_obj_E = sip_setup_timer(conn_obj, sip_trans, msg,
2682882Svi117747 			    sip_trans->sip_xaction_TE, SIP_XACTION_TIMER_E);
2692882Svi117747 			if (timer_obj_E == NULL) {
2702882Svi117747 				error = ENOMEM;
2712882Svi117747 				goto error_ret;
2722882Svi117747 			}
2732882Svi117747 		}
2742882Svi117747 		/*
2752882Svi117747 		 * Start transaction Timer F
2762882Svi117747 		 */
2772882Svi117747 		timer_obj_F = sip_setup_timer(conn_obj, sip_trans, NULL,
2782882Svi117747 		    sip_trans->sip_xaction_TF, SIP_XACTION_TIMER_F);
2792882Svi117747 		if (timer_obj_F == NULL) {
2802882Svi117747 			error = ENOMEM;
2812882Svi117747 			goto error_ret;
2822882Svi117747 		}
2832882Svi117747 		if (timer_obj_E != NULL) {
2842882Svi117747 			SIP_SCHED_TIMER(sip_trans->sip_xaction_TE, timer_obj_E,
2852882Svi117747 			    sip_xaction_state_timer_fire);
2862882Svi117747 			if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TE)) {
2872882Svi117747 				error = ENOMEM;
2882882Svi117747 				goto error_ret;
2892882Svi117747 			}
2902882Svi117747 		}
2912882Svi117747 		SIP_SCHED_TIMER(sip_trans->sip_xaction_TF, timer_obj_F,
2922882Svi117747 		    sip_xaction_state_timer_fire);
2932882Svi117747 		if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TF)) {
2942882Svi117747 			if (timer_obj_E != NULL)
2952882Svi117747 				SIP_CANCEL_TIMER(sip_trans->sip_xaction_TE)
2962882Svi117747 			error = ENOMEM;
2972882Svi117747 			goto error_ret;
2982882Svi117747 		}
2992882Svi117747 		sip_trans->sip_xaction_state = SIP_CLNT_TRYING;
3002882Svi117747 	}
3012882Svi117747 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
3022882Svi117747 	if (sip_xaction_ulp_state_cb != NULL) {
3032882Svi117747 		sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
3042882Svi117747 		    (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
3052882Svi117747 	}
3062882Svi117747 	return (0);
3072882Svi117747 
3082882Svi117747 error_ret:
3092882Svi117747 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
3102882Svi117747 	if (timer_obj_A != NULL)
3112882Svi117747 		free(timer_obj_A);
3122882Svi117747 	if (timer_obj_B != NULL)
3132882Svi117747 		free(timer_obj_B);
3142882Svi117747 	if (timer_obj_E != NULL)
3152882Svi117747 		free(timer_obj_E);
3162882Svi117747 	if (timer_obj_F != NULL)
3172882Svi117747 		free(timer_obj_F);
3182882Svi117747 	return (error);
3192882Svi117747 }
3202882Svi117747 
3212882Svi117747 /*
3222882Svi117747  * Send a response out
3232882Svi117747  */
3242882Svi117747 static int
sip_srv_xaction_output(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t * msg)3252882Svi117747 sip_srv_xaction_output(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
3262882Svi117747     _sip_msg_t *msg)
3272882Svi117747 {
3282882Svi117747 	int		ret;
3292882Svi117747 
3302882Svi117747 	if (sip_trans->sip_xaction_method == INVITE)
3312882Svi117747 		ret = sip_srv_xaction_inv_res(conn_obj, sip_trans, msg);
3322882Svi117747 	else
3332882Svi117747 		ret = sip_srv_xaction_noninv_res(conn_obj, sip_trans, msg);
3342882Svi117747 	return (ret);
3352882Svi117747 }
3362882Svi117747 
3372882Svi117747 /*
3382882Svi117747  * Send a INVITE response out
3392882Svi117747  */
3402882Svi117747 static int
sip_srv_xaction_inv_res(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t * msg)3412882Svi117747 sip_srv_xaction_inv_res(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
3422882Svi117747     _sip_msg_t *msg)
3432882Svi117747 {
3442882Svi117747 	int			resp_code;
3452882Svi117747 	sip_xaction_time_obj_t	*timer_obj_G = NULL;
3462882Svi117747 	sip_xaction_time_obj_t	*timer_obj_H = NULL;
3472882Svi117747 	sip_message_type_t	*sip_msg_info = msg->sip_msg_req_res;
3482882Svi117747 	int			prev_state;
3492882Svi117747 	boolean_t		isreliable;
3502882Svi117747 
3512882Svi117747 	isreliable = sip_is_conn_reliable(conn_obj);
3522882Svi117747 
3532882Svi117747 	resp_code = sip_msg_info->sip_resp_code;
3542882Svi117747 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
3552882Svi117747 	prev_state = sip_trans->sip_xaction_state;
3562882Svi117747 	switch (sip_trans->sip_xaction_state) {
3572882Svi117747 		case SIP_SRV_INV_PROCEEDING:
3582882Svi117747 			if (SIP_PROVISIONAL_RESP(resp_code)) {
3592882Svi117747 				if (sip_trans->sip_xaction_last_msg != NULL) {
3602882Svi117747 					SIP_MSG_REFCNT_DECR(
3612882Svi117747 					    sip_trans->sip_xaction_last_msg);
3622882Svi117747 					sip_trans->sip_xaction_last_msg = NULL;
3632882Svi117747 				}
3642882Svi117747 				SIP_MSG_REFCNT_INCR(msg);
3652882Svi117747 				sip_trans->sip_xaction_last_msg = msg;
3662882Svi117747 				(void) sip_add_conn_obj_cache(conn_obj,
3672882Svi117747 				    (void *)sip_trans);
3682882Svi117747 			} else if (SIP_OK_RESP(resp_code)) {
3692882Svi117747 				sip_trans->sip_xaction_state =
3702882Svi117747 				    SIP_SRV_INV_TERMINATED;
3712882Svi117747 			} else  if (SIP_NONOK_FINAL_RESP(resp_code)) {
3722882Svi117747 				if (sip_trans->sip_xaction_last_msg != NULL) {
3732882Svi117747 					SIP_MSG_REFCNT_DECR(
3742882Svi117747 					    sip_trans->sip_xaction_last_msg);
3752882Svi117747 					sip_trans->sip_xaction_last_msg = NULL;
3762882Svi117747 				}
3772882Svi117747 				SIP_MSG_REFCNT_INCR(msg);
3782882Svi117747 				sip_trans->sip_xaction_last_msg = msg;
3792882Svi117747 				(void) sip_add_conn_obj_cache(conn_obj,
3802882Svi117747 				    (void *)sip_trans);
3812882Svi117747 				/*
3822882Svi117747 				 * For unreliable transport start timer G
3832882Svi117747 				 */
3842882Svi117747 				if (!isreliable) {
3852882Svi117747 					timer_obj_G = sip_setup_timer(
3862882Svi117747 					    conn_obj, sip_trans,
3872882Svi117747 					    NULL, sip_trans->sip_xaction_TG,
3882882Svi117747 					    SIP_XACTION_TIMER_G);
3892882Svi117747 					if (timer_obj_G == NULL) {
3902882Svi117747 						(void) pthread_mutex_unlock(
3912882Svi117747 						    &sip_trans->
3922882Svi117747 						    sip_xaction_mutex);
3932882Svi117747 						return (ENOMEM);
3942882Svi117747 					}
3952882Svi117747 				}
3962882Svi117747 				/*
3972882Svi117747 				 * Start Timer H
3982882Svi117747 				 */
3992882Svi117747 				timer_obj_H = sip_setup_timer(
4002882Svi117747 				    conn_obj, sip_trans,
4012882Svi117747 				    NULL, sip_trans->sip_xaction_TH,
4022882Svi117747 				    SIP_XACTION_TIMER_H);
4032882Svi117747 				if (timer_obj_H == NULL) {
4042882Svi117747 					if (timer_obj_G != NULL)
4052882Svi117747 						free(timer_obj_G);
4062882Svi117747 					(void) pthread_mutex_unlock(
4072882Svi117747 					    &sip_trans->sip_xaction_mutex);
4082882Svi117747 					return (ENOMEM);
4092882Svi117747 				}
4102882Svi117747 				if (timer_obj_G != NULL) {
4112882Svi117747 					SIP_SCHED_TIMER(
4122882Svi117747 					    sip_trans->sip_xaction_TG,
4132882Svi117747 					    timer_obj_G,
4142882Svi117747 					    sip_xaction_state_timer_fire);
4152882Svi117747 					if (!SIP_IS_TIMER_RUNNING(
4162882Svi117747 					    sip_trans->sip_xaction_TG)) {
4172882Svi117747 						(void) pthread_mutex_unlock(
4182882Svi117747 						    &sip_trans->
4192882Svi117747 						    sip_xaction_mutex);
4202882Svi117747 						free(timer_obj_G);
4212882Svi117747 						return (ENOMEM);
4222882Svi117747 					}
4232882Svi117747 				}
4242882Svi117747 				if (timer_obj_H != NULL) {
4252882Svi117747 					SIP_SCHED_TIMER(
4262882Svi117747 					    sip_trans->sip_xaction_TH,
4272882Svi117747 					    timer_obj_H,
4282882Svi117747 					    sip_xaction_state_timer_fire);
4292882Svi117747 					if (!SIP_IS_TIMER_RUNNING(
4302882Svi117747 					    sip_trans->sip_xaction_TH)) {
4312882Svi117747 						if (timer_obj_G != NULL) {
4322882Svi117747 							SIP_CANCEL_TIMER(
4332882Svi117747 							    sip_trans->
4342882Svi117747 							    sip_xaction_TG);
4352882Svi117747 							free(timer_obj_G);
4362882Svi117747 						}
4372882Svi117747 						(void) pthread_mutex_unlock(
4382882Svi117747 						    &sip_trans->
4392882Svi117747 						    sip_xaction_mutex);
4402882Svi117747 						free(timer_obj_H);
4412882Svi117747 						return (ENOMEM);
4422882Svi117747 					}
4432882Svi117747 				}
4442882Svi117747 				sip_trans->sip_xaction_state =
4452882Svi117747 				    SIP_SRV_INV_COMPLETED;
4462882Svi117747 			}
4472882Svi117747 			break;
4482882Svi117747 		default:
4492882Svi117747 			(void) pthread_mutex_unlock(
4502882Svi117747 			    &sip_trans->sip_xaction_mutex);
4512882Svi117747 			return (EPROTO);
4522882Svi117747 	}
4532882Svi117747 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
4542882Svi117747 	if (prev_state != sip_trans->sip_xaction_state &&
4552882Svi117747 	    sip_xaction_ulp_state_cb != NULL) {
4562882Svi117747 		sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
4572882Svi117747 		    (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
4582882Svi117747 	}
4592882Svi117747 	return (0);
4602882Svi117747 }
4612882Svi117747 
4622882Svi117747 /*
4632882Svi117747  *  Send a NON-INVITE response out
4642882Svi117747  */
4652882Svi117747 static int
sip_srv_xaction_noninv_res(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t * msg)4662882Svi117747 sip_srv_xaction_noninv_res(sip_conn_object_t conn_obj,
4672882Svi117747     sip_xaction_t *sip_trans, _sip_msg_t *msg)
4682882Svi117747 {
4692882Svi117747 	int			resp_code;
4702882Svi117747 	sip_xaction_time_obj_t	*timer_obj_J = NULL;
4712882Svi117747 	sip_message_type_t	*sip_msg_info = msg->sip_msg_req_res;
4722882Svi117747 	int			prev_state;
4732882Svi117747 	boolean_t		isreliable;
4742882Svi117747 
4752882Svi117747 	resp_code = sip_msg_info->sip_resp_code;
4762882Svi117747 	isreliable = sip_is_conn_reliable(conn_obj);
4772882Svi117747 
4782882Svi117747 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
4792882Svi117747 	prev_state = sip_trans->sip_xaction_state;
4802882Svi117747 	switch (sip_trans->sip_xaction_state) {
4812882Svi117747 		case SIP_SRV_TRYING:
4822882Svi117747 			if (sip_trans->sip_xaction_last_msg != NULL) {
4832882Svi117747 				SIP_MSG_REFCNT_DECR(
4842882Svi117747 				    sip_trans->sip_xaction_last_msg);
4852882Svi117747 				sip_trans->sip_xaction_last_msg = NULL;
4862882Svi117747 			}
4872882Svi117747 			SIP_MSG_REFCNT_INCR(msg);
4882882Svi117747 			sip_trans->sip_xaction_last_msg = msg;
4892882Svi117747 			(void) sip_add_conn_obj_cache(conn_obj,
4902882Svi117747 			    (void *)sip_trans);
4912882Svi117747 			if (SIP_PROVISIONAL_RESP(resp_code)) {
4922882Svi117747 				sip_trans->sip_xaction_state =
4932882Svi117747 				    SIP_SRV_NONINV_PROCEEDING;
4942882Svi117747 			} else if (SIP_FINAL_RESP(resp_code)) {
4952882Svi117747 				/*
4962882Svi117747 				 * For unreliable transports, start Timer J
4972882Svi117747 				 */
4982882Svi117747 				if (!isreliable) {
4992882Svi117747 					timer_obj_J = sip_setup_timer(
5002882Svi117747 					    conn_obj, sip_trans,
5012882Svi117747 					    NULL, sip_trans->sip_xaction_TJ,
5022882Svi117747 					    SIP_XACTION_TIMER_J);
5032882Svi117747 					if (timer_obj_J == NULL) {
5042882Svi117747 						(void) pthread_mutex_unlock(&
5052882Svi117747 						    sip_trans->
5062882Svi117747 						    sip_xaction_mutex);
5072882Svi117747 						return (ENOMEM);
5082882Svi117747 					}
5092882Svi117747 					SIP_SCHED_TIMER(
5102882Svi117747 					    sip_trans->sip_xaction_TJ,
5112882Svi117747 					    timer_obj_J,
5122882Svi117747 					    sip_xaction_state_timer_fire);
5132882Svi117747 					if (!SIP_IS_TIMER_RUNNING(
5142882Svi117747 					    sip_trans->sip_xaction_TJ)) {
5152882Svi117747 						(void) pthread_mutex_unlock(&
5162882Svi117747 						    sip_trans->
5172882Svi117747 						    sip_xaction_mutex);
5182882Svi117747 						free(timer_obj_J);
5192882Svi117747 						return (ENOMEM);
5202882Svi117747 					}
5212882Svi117747 					sip_trans->sip_xaction_state =
5222882Svi117747 					    SIP_SRV_NONINV_COMPLETED;
5232882Svi117747 				} else {
5242882Svi117747 					sip_trans->sip_xaction_state =
5252882Svi117747 					    SIP_SRV_NONINV_TERMINATED;
5262882Svi117747 				}
5272882Svi117747 			}
5282882Svi117747 			break;
5292882Svi117747 		case SIP_SRV_NONINV_PROCEEDING:
5302882Svi117747 			if (sip_trans->sip_xaction_last_msg != NULL) {
5312882Svi117747 				SIP_MSG_REFCNT_DECR(
5322882Svi117747 				    sip_trans->sip_xaction_last_msg);
5332882Svi117747 				sip_trans->sip_xaction_last_msg = NULL;
5342882Svi117747 			}
5352882Svi117747 			SIP_MSG_REFCNT_INCR(msg);
5362882Svi117747 			sip_trans->sip_xaction_last_msg = msg;
5372882Svi117747 			(void) sip_add_conn_obj_cache(conn_obj,
5382882Svi117747 			    (void *)sip_trans);
5392882Svi117747 			if (SIP_PROVISIONAL_RESP(resp_code)) {
5402882Svi117747 				break;
5412882Svi117747 			} else if (SIP_FINAL_RESP(resp_code)) {
5422882Svi117747 				/*
5432882Svi117747 				 * For unreliable transports, start Timer J
5442882Svi117747 				 */
5452882Svi117747 				if (!isreliable) {
5462882Svi117747 					timer_obj_J = sip_setup_timer(
5472882Svi117747 					    conn_obj, sip_trans,
5482882Svi117747 					    NULL, sip_trans->sip_xaction_TJ,
5492882Svi117747 					    SIP_XACTION_TIMER_J);
5502882Svi117747 					if (timer_obj_J == NULL) {
5512882Svi117747 						(void) pthread_mutex_unlock(&
5522882Svi117747 						    sip_trans->
5532882Svi117747 						    sip_xaction_mutex);
5542882Svi117747 						return (ENOMEM);
5552882Svi117747 					}
5562882Svi117747 					SIP_SCHED_TIMER(
5572882Svi117747 					    sip_trans->sip_xaction_TJ,
5582882Svi117747 					    timer_obj_J,
5592882Svi117747 					    sip_xaction_state_timer_fire);
5602882Svi117747 					if (!SIP_IS_TIMER_RUNNING(
5612882Svi117747 					    sip_trans->sip_xaction_TJ)) {
5622882Svi117747 						(void) pthread_mutex_unlock(&
5632882Svi117747 						    sip_trans->
5642882Svi117747 						    sip_xaction_mutex);
5652882Svi117747 						free(timer_obj_J);
5662882Svi117747 						return (ENOMEM);
5672882Svi117747 					}
5682882Svi117747 					sip_trans->sip_xaction_state =
5692882Svi117747 					    SIP_SRV_NONINV_COMPLETED;
5702882Svi117747 				} else {
5712882Svi117747 					sip_trans->sip_xaction_state =
5722882Svi117747 					    SIP_SRV_NONINV_TERMINATED;
5732882Svi117747 				}
5742882Svi117747 			}
5752882Svi117747 			break;
5762882Svi117747 		default:
5772882Svi117747 			(void) pthread_mutex_unlock(
5782882Svi117747 			    &sip_trans->sip_xaction_mutex);
5792882Svi117747 			return (EPROTO);
5802882Svi117747 	}
5812882Svi117747 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
5822882Svi117747 	if (prev_state != sip_trans->sip_xaction_state &&
5832882Svi117747 	    sip_xaction_ulp_state_cb != NULL) {
5842882Svi117747 		sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
5852882Svi117747 		    (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
5862882Svi117747 	}
5872882Svi117747 	return (0);
5882882Svi117747 }
5892882Svi117747 
5902882Svi117747 
5912882Svi117747 /*
5922882Svi117747  * -------------------------- Input Routines ---------------------------
5932882Svi117747  */
5942882Svi117747 
5952882Svi117747 /*
5962882Svi117747  * Process an incoming SIP message Request or Response
5972882Svi117747  */
5982882Svi117747 int
sip_xaction_input(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t ** sip_msg)5992882Svi117747 sip_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
6002882Svi117747     _sip_msg_t **sip_msg)
6012882Svi117747 {
6022882Svi117747 	sip_message_type_t	*sip_msg_info;
6032882Svi117747 	int			ret;
6042882Svi117747 
6052882Svi117747 	sip_msg_info = (*sip_msg)->sip_msg_req_res;
606*5842Sgm209912 
607*5842Sgm209912 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
608*5842Sgm209912 	sip_trans->sip_xaction_msgcnt++;
609*5842Sgm209912 	sip_add_log(&sip_trans->sip_xaction_log[sip_trans->sip_xaction_state],
610*5842Sgm209912 	    (sip_msg_t)*sip_msg, sip_trans->sip_xaction_msgcnt,
611*5842Sgm209912 	    SIP_TRANSACTION_LOG);
612*5842Sgm209912 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
613*5842Sgm209912 
6142882Svi117747 	if (sip_msg_info->is_request)
6152882Svi117747 		ret = sip_srv_xaction_input(conn_obj, sip_trans, sip_msg);
6162882Svi117747 	else
6172882Svi117747 		ret = sip_clnt_xaction_input(conn_obj, sip_trans, sip_msg);
6182882Svi117747 	return (ret);
6192882Svi117747 }
6202882Svi117747 
6212882Svi117747 /*
6222882Svi117747  * Process a Request from the transport
6232882Svi117747  */
6242882Svi117747 static int
sip_srv_xaction_input(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t ** sip_msg)6252882Svi117747 sip_srv_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
6262882Svi117747     _sip_msg_t **sip_msg)
6272882Svi117747 {
6282882Svi117747 	sip_message_type_t	*sip_msg_info;
6292882Svi117747 	_sip_msg_t		*msg = *sip_msg;
6302882Svi117747 	int			prev_state;
6312882Svi117747 	boolean_t		isreliable;
6322882Svi117747 
6332882Svi117747 	sip_msg_info = msg->sip_msg_req_res;
6342882Svi117747 	isreliable = sip_is_conn_reliable(conn_obj);
6352882Svi117747 
6362882Svi117747 	/*
6372882Svi117747 	 * Cancel if the original transaction has not yet got a final
6382882Svi117747 	 * response and send a 487 response.
6392882Svi117747 	 */
6402882Svi117747 	if (sip_msg_info->sip_req_method == ACK) {
6412882Svi117747 		_sip_msg_t		*sip_last_resp;
6422882Svi117747 		const sip_str_t		*resp_to_tag;
6432882Svi117747 		const sip_str_t		*req_to_tag;
6442882Svi117747 		int			error;
6452882Svi117747 		sip_message_type_t	*last_msg_info;
6462882Svi117747 
6472882Svi117747 		(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
6482882Svi117747 
6492882Svi117747 		if (sip_trans->sip_xaction_last_msg != NULL)
6502882Svi117747 			sip_last_resp = sip_trans->sip_xaction_last_msg;
6512882Svi117747 		else
6522882Svi117747 			sip_last_resp = sip_trans->sip_xaction_orig_msg;
6532882Svi117747 		last_msg_info = sip_last_resp->sip_msg_req_res;
6542882Svi117747 		if (last_msg_info->is_request) {
6552882Svi117747 			(void) pthread_mutex_unlock(
6562882Svi117747 			    &sip_trans->sip_xaction_mutex);
6572882Svi117747 			return (0);
6582882Svi117747 		}
6592882Svi117747 		req_to_tag = sip_get_to_tag((sip_msg_t)msg, &error);
6602882Svi117747 		if (req_to_tag == NULL || error != 0) {
6612882Svi117747 			(void) pthread_mutex_unlock(
6622882Svi117747 			    &sip_trans->sip_xaction_mutex);
6632882Svi117747 			return (0);
6642882Svi117747 		}
6652882Svi117747 		resp_to_tag = sip_get_to_tag((sip_msg_t)sip_last_resp,
6662882Svi117747 		    &error);
6672882Svi117747 		if (req_to_tag == NULL || error != 0) {
6682882Svi117747 			(void) pthread_mutex_unlock(
6692882Svi117747 			    &sip_trans->sip_xaction_mutex);
6702882Svi117747 			return (0);
6712882Svi117747 		}
6722882Svi117747 		if (resp_to_tag->sip_str_len != req_to_tag->sip_str_len ||
6732882Svi117747 		    strncmp(resp_to_tag->sip_str_ptr, req_to_tag->sip_str_ptr,
674*5842Sgm209912 		    req_to_tag->sip_str_len) != 0) {
6752882Svi117747 			(void) pthread_mutex_unlock(
6762882Svi117747 			    &sip_trans->sip_xaction_mutex);
6772882Svi117747 			return (0);
6782882Svi117747 		}
6792882Svi117747 		prev_state = sip_trans->sip_xaction_state;
6802882Svi117747 		if (sip_trans->sip_xaction_state == SIP_SRV_INV_COMPLETED) {
6812882Svi117747 			sip_xaction_time_obj_t	*timer_obj_I = NULL;
6822882Svi117747 
6832882Svi117747 			SIP_CANCEL_TIMER(sip_trans->sip_xaction_TG);
6842882Svi117747 			/*
6852882Svi117747 			 * Cancel Timer H and goto TERMINATED state for
6862882Svi117747 			 * reliable transports.
6872882Svi117747 			 */
6882882Svi117747 			if (isreliable) {
6892882Svi117747 				SIP_CANCEL_TIMER(
6902882Svi117747 				    sip_trans->sip_xaction_TH);
6912882Svi117747 				sip_trans->sip_xaction_state =
6922882Svi117747 				    SIP_SRV_INV_TERMINATED;
6932882Svi117747 				(void) pthread_mutex_unlock(
6942882Svi117747 				    &sip_trans->sip_xaction_mutex);
6952882Svi117747 				if (sip_xaction_ulp_state_cb != NULL) {
6962882Svi117747 					sip_xaction_ulp_state_cb(
6972882Svi117747 					    (sip_transaction_t)sip_trans,
6982882Svi117747 					    (sip_msg_t)msg, prev_state,
6992882Svi117747 					    sip_trans->sip_xaction_state);
7002882Svi117747 				}
7012882Svi117747 				return (0);
7022882Svi117747 			}
7032882Svi117747 			/*
7042882Svi117747 			 * For unreliable transports, start TIMER I and
7052882Svi117747 			 * transition to CONFIRMED state.
7062882Svi117747 			 */
7072882Svi117747 			timer_obj_I = sip_setup_timer(conn_obj, sip_trans,
7082882Svi117747 			    NULL,
7092882Svi117747 			    sip_trans->sip_xaction_TI, SIP_XACTION_TIMER_I);
7102882Svi117747 			if (timer_obj_I == NULL) {
7112882Svi117747 				(void) pthread_mutex_unlock(
7122882Svi117747 				    &sip_trans->sip_xaction_mutex);
7132882Svi117747 				return (ENOMEM);
7142882Svi117747 			}
7152882Svi117747 			SIP_SCHED_TIMER(sip_trans->sip_xaction_TI,
7162882Svi117747 			    timer_obj_I, sip_xaction_state_timer_fire);
7172882Svi117747 			if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TI)) {
7182882Svi117747 				(void) pthread_mutex_unlock(
7192882Svi117747 				    &sip_trans->sip_xaction_mutex);
7202882Svi117747 				free(timer_obj_I);
7212882Svi117747 				return (ENOMEM);
7222882Svi117747 			}
7232882Svi117747 			sip_trans->sip_xaction_state = SIP_SRV_CONFIRMED;
7242882Svi117747 		}
7252882Svi117747 		(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
7262882Svi117747 		if (prev_state != sip_trans->sip_xaction_state &&
7272882Svi117747 		    sip_xaction_ulp_state_cb != NULL) {
7282882Svi117747 			sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
7292882Svi117747 			    (sip_msg_t)msg, prev_state,
7302882Svi117747 			    sip_trans->sip_xaction_state);
7312882Svi117747 		}
7322882Svi117747 		return (0);
7332882Svi117747 	} else if (sip_msg_info->sip_req_method == CANCEL) {
7342882Svi117747 		if (sip_trans->sip_xaction_method == INVITE) {
7352882Svi117747 			(void) pthread_mutex_unlock(
7362882Svi117747 			    &sip_trans->sip_xaction_mutex);
7372882Svi117747 			return (0);
7382882Svi117747 		}
7392882Svi117747 	}
7402882Svi117747 	if (sip_msg_info->sip_req_method == INVITE) {
7412882Svi117747 		(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
742*5842Sgm209912 		if (sip_trans->sip_xaction_method != INVITE) {
743*5842Sgm209912 			sip_write_to_log((void *)sip_trans,
744*5842Sgm209912 			    SIP_TRANSACTION_LOG | SIP_ASSERT_ERROR, __FILE__,
745*5842Sgm209912 			    __LINE__);
746*5842Sgm209912 		}
7472882Svi117747 		assert(sip_trans->sip_xaction_method == INVITE);
7482882Svi117747 		/*
7492882Svi117747 		 * Retransmitted invite
7502882Svi117747 		 */
7512882Svi117747 		switch (sip_trans->sip_xaction_state) {
7522882Svi117747 			case SIP_SRV_INV_PROCEEDING:
7532882Svi117747 			case SIP_SRV_INV_COMPLETED:
7542882Svi117747 				if (sip_trans->sip_xaction_last_msg != NULL) {
755*5842Sgm209912 					_sip_msg_t		*new_msg;
756*5842Sgm209912 					sip_message_type_t	*msg_info;
757*5842Sgm209912 					int			resp;
7582882Svi117747 
7592882Svi117747 					new_msg =
7602882Svi117747 					    sip_trans->sip_xaction_last_msg;
761*5842Sgm209912 					msg_info = new_msg->sip_msg_req_res;
762*5842Sgm209912 					if (msg_info == NULL || msg_info->
763*5842Sgm209912 					    is_request) {
764*5842Sgm209912 						sip_write_to_log((void *)
765*5842Sgm209912 						    sip_trans,
766*5842Sgm209912 						    SIP_TRANSACTION_LOG |
767*5842Sgm209912 						    SIP_ASSERT_ERROR, __FILE__,
768*5842Sgm209912 						    __LINE__);
769*5842Sgm209912 					}
770*5842Sgm209912 					assert(msg_info != NULL && !msg_info->
771*5842Sgm209912 					    is_request);
772*5842Sgm209912 					resp = msg_info->sip_resp_code;
773*5842Sgm209912 					SIP_UPDATE_COUNTERS(B_FALSE, 0, resp,
774*5842Sgm209912 					    B_TRUE, new_msg->sip_msg_len);
775*5842Sgm209912 					++sip_trans->sip_xaction_msgcnt;
776*5842Sgm209912 					sip_add_log(&sip_trans->sip_xaction_log[
777*5842Sgm209912 					    sip_trans->sip_xaction_state],
778*5842Sgm209912 					    new_msg, sip_trans->
779*5842Sgm209912 					    sip_xaction_msgcnt,
780*5842Sgm209912 					    SIP_TRANSACTION_LOG);
7812882Svi117747 					(void) sip_stack_send(conn_obj,
7822882Svi117747 					    new_msg->sip_msg_buf,
7832882Svi117747 					    new_msg->sip_msg_len);
7842882Svi117747 				}
7852882Svi117747 				break;
7862882Svi117747 			default:
7872882Svi117747 				(void) pthread_mutex_unlock(
7882882Svi117747 				    &sip_trans->sip_xaction_mutex);
7892882Svi117747 				return (EPROTO);
7902882Svi117747 		}
7912882Svi117747 		(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
792*5842Sgm209912 		/*
793*5842Sgm209912 		 * We need to account for this invite received by the stack
794*5842Sgm209912 		 * before we free that message.
795*5842Sgm209912 		 */
796*5842Sgm209912 		SIP_UPDATE_COUNTERS(B_TRUE, INVITE, 0, B_FALSE,
797*5842Sgm209912 		    msg->sip_msg_len);
7982882Svi117747 		sip_free_msg((sip_msg_t)msg);
7992882Svi117747 		*sip_msg = NULL;
8002882Svi117747 		return (0);
8012882Svi117747 	}
8022882Svi117747 	/*
8032882Svi117747 	 * Retransmitted request
8042882Svi117747 	 */
805*5842Sgm209912 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
806*5842Sgm209912 	if (sip_trans->sip_xaction_method == INVITE) {
807*5842Sgm209912 		sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
808*5842Sgm209912 		    SIP_ASSERT_ERROR, __FILE__, __LINE__);
809*5842Sgm209912 	}
8102882Svi117747 	assert(sip_trans->sip_xaction_method != INVITE);
8112882Svi117747 	switch (sip_trans->sip_xaction_state) {
8122882Svi117747 		case SIP_SRV_NONINV_PROCEEDING:
8132882Svi117747 		case SIP_SRV_NONINV_COMPLETED:
8142882Svi117747 			if (sip_trans->sip_xaction_last_msg != NULL) {
815*5842Sgm209912 				_sip_msg_t		*new_msg;
816*5842Sgm209912 				sip_message_type_t	*msg_info;
817*5842Sgm209912 				int			resp;
8182882Svi117747 
8192882Svi117747 				new_msg = sip_trans->sip_xaction_last_msg;
820*5842Sgm209912 				msg_info = new_msg->sip_msg_req_res;
821*5842Sgm209912 				if (msg_info == NULL || msg_info->is_request) {
822*5842Sgm209912 					sip_write_to_log((void *)sip_trans,
823*5842Sgm209912 					    SIP_TRANSACTION_LOG |
824*5842Sgm209912 					    SIP_ASSERT_ERROR, __FILE__,
825*5842Sgm209912 					    __LINE__);
826*5842Sgm209912 					}
827*5842Sgm209912 				assert(msg_info != NULL && !msg_info->
828*5842Sgm209912 				    is_request);
829*5842Sgm209912 				resp = msg_info->sip_resp_code;
830*5842Sgm209912 				SIP_UPDATE_COUNTERS(B_FALSE, 0, resp, B_TRUE,
831*5842Sgm209912 				    new_msg->sip_msg_len);
832*5842Sgm209912 				++sip_trans->sip_xaction_msgcnt;
833*5842Sgm209912 				sip_add_log(&sip_trans->sip_xaction_log[
834*5842Sgm209912 				    sip_trans->sip_xaction_state], new_msg,
835*5842Sgm209912 				    sip_trans->sip_xaction_msgcnt,
836*5842Sgm209912 				    SIP_TRANSACTION_LOG);
8372882Svi117747 				(void) sip_stack_send(conn_obj,
8382882Svi117747 				    new_msg->sip_msg_buf, new_msg->sip_msg_len);
8392882Svi117747 			}
8402882Svi117747 			break;
8412882Svi117747 		default:
8422882Svi117747 			(void) pthread_mutex_unlock(
8432882Svi117747 			    &sip_trans->sip_xaction_mutex);
8442882Svi117747 			return (EPROTO);
8452882Svi117747 	}
8462882Svi117747 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
847*5842Sgm209912 	/*
848*5842Sgm209912 	 * We need to account for the retransmitted non-INVITE request here.
849*5842Sgm209912 	 * When we return from here the msg will be freed and we will not
850*5842Sgm209912 	 * be able to capture the details at sip_process_new_packet()
851*5842Sgm209912 	 */
852*5842Sgm209912 	SIP_UPDATE_COUNTERS(B_TRUE, sip_msg_info->sip_req_method, 0, B_FALSE,
853*5842Sgm209912 	    msg->sip_msg_len);
8542882Svi117747 	sip_free_msg((sip_msg_t)msg);
8552882Svi117747 	*sip_msg = NULL;
8562882Svi117747 	return (0);
8572882Svi117747 }
8582882Svi117747 
8592882Svi117747 /*
8602882Svi117747  * Process a Response
8612882Svi117747  */
8622882Svi117747 static int
sip_clnt_xaction_input(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t ** msg)8632882Svi117747 sip_clnt_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
8642882Svi117747     _sip_msg_t **msg)
8652882Svi117747 {
8662882Svi117747 	int		ret;
8672882Svi117747 
8682882Svi117747 	if (sip_trans->sip_xaction_method == INVITE)
8692882Svi117747 		ret = sip_clnt_xaction_inv_res(conn_obj, sip_trans, msg);
8702882Svi117747 	else
8712882Svi117747 		ret = sip_clnt_xaction_noninv_res(conn_obj, sip_trans, msg);
8722882Svi117747 
8732882Svi117747 	return (ret);
8742882Svi117747 }
8752882Svi117747 
8762882Svi117747 static int
sip_create_send_nonOKack(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t * msg,boolean_t copy)8772882Svi117747 sip_create_send_nonOKack(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
8782882Svi117747     _sip_msg_t *msg, boolean_t copy)
8792882Svi117747 {
8802882Svi117747 	_sip_msg_t	*ack_msg;
8812882Svi117747 	int		ret = 0;
8822882Svi117747 
8832882Svi117747 	ack_msg = (_sip_msg_t *)sip_new_msg();
8842882Svi117747 	if (ack_msg == NULL)
8852882Svi117747 		return (ENOMEM);
8862882Svi117747 	if ((ret = sip_create_nonOKack(
8872882Svi117747 	    (sip_msg_t)sip_trans->sip_xaction_orig_msg, (sip_msg_t)msg,
8882882Svi117747 	    (sip_msg_t)ack_msg)) != 0) {
8892882Svi117747 		sip_free_msg((sip_msg_t)ack_msg);
8902882Svi117747 		return (ret);
8912882Svi117747 	}
892*5842Sgm209912 	SIP_UPDATE_COUNTERS(B_TRUE, ACK, 0, B_TRUE, ack_msg->sip_msg_len);
893*5842Sgm209912 	++sip_trans->sip_xaction_msgcnt;
894*5842Sgm209912 	sip_add_log(&sip_trans->sip_xaction_log[sip_trans->sip_xaction_state],
895*5842Sgm209912 	    ack_msg, sip_trans->sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
8962882Svi117747 	if ((ret = sip_stack_send(conn_obj, ack_msg->sip_msg_buf,
8972882Svi117747 	    ack_msg->sip_msg_len)) != 0) {
8982882Svi117747 		sip_free_msg((sip_msg_t)ack_msg);
8992882Svi117747 		return (ret);
9002882Svi117747 	}
9012882Svi117747 	if (copy) {
9022882Svi117747 		SIP_MSG_REFCNT_INCR(ack_msg);
9032882Svi117747 		if (sip_trans->sip_xaction_last_msg != NULL) {
9042882Svi117747 			SIP_MSG_REFCNT_DECR(sip_trans->sip_xaction_last_msg);
9052882Svi117747 			sip_trans->sip_xaction_last_msg = NULL;
9062882Svi117747 		}
9072882Svi117747 		sip_trans->sip_xaction_last_msg = ack_msg;
9082882Svi117747 	}
9092882Svi117747 	sip_free_msg((sip_msg_t)ack_msg);
9102882Svi117747 	return (0);
9112882Svi117747 }
9122882Svi117747 
9132882Svi117747 /*
9142882Svi117747  * Process a INVITE Response
9152882Svi117747  */
9162882Svi117747 static int
sip_clnt_xaction_inv_res(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t ** sip_msg)9172882Svi117747 sip_clnt_xaction_inv_res(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
9182882Svi117747     _sip_msg_t **sip_msg)
9192882Svi117747 {
9202882Svi117747 	int			resp_code;
9212882Svi117747 	_sip_msg_t		*msg = *sip_msg;
9222882Svi117747 	sip_xaction_time_obj_t	*timer_obj_D = NULL;
9232882Svi117747 	sip_message_type_t	*sip_msg_info;
9242882Svi117747 	int			prev_state;
9252882Svi117747 	boolean_t		isreliable;
9262882Svi117747 
927*5842Sgm209912 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
928*5842Sgm209912 	if (msg->sip_msg_req_res == NULL) {
929*5842Sgm209912 		sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
930*5842Sgm209912 		    SIP_ASSERT_ERROR, __FILE__, __LINE__);
931*5842Sgm209912 	}
9322882Svi117747 	assert(msg->sip_msg_req_res != NULL);
9332882Svi117747 
9342882Svi117747 	sip_msg_info = msg->sip_msg_req_res;
9352882Svi117747 	resp_code = sip_msg_info->sip_resp_code;
9362882Svi117747 	isreliable = sip_is_conn_reliable(conn_obj);
9372882Svi117747 
9382882Svi117747 	prev_state = sip_trans->sip_xaction_state;
9392882Svi117747 	switch (sip_trans->sip_xaction_state) {
9402882Svi117747 		case SIP_CLNT_CALLING:
9412882Svi117747 			if (SIP_PROVISIONAL_RESP(resp_code)) {
9422882Svi117747 				/*
9432882Svi117747 				 * sip_trans->sip_xaction_last_msg ?
9442882Svi117747 				 */
9452882Svi117747 				SIP_CANCEL_TIMER(
9462882Svi117747 				    sip_trans->sip_xaction_TA);
9472882Svi117747 				sip_trans->sip_xaction_state =
9482882Svi117747 				    SIP_CLNT_INV_PROCEEDING;
9492882Svi117747 			} else if (SIP_OK_RESP(resp_code)) {
9502882Svi117747 				/*
9512882Svi117747 				 * sip_trans->sip_xaction_last_msg ?
9522882Svi117747 				 */
9532882Svi117747 				SIP_CANCEL_TIMER(
9542882Svi117747 				    sip_trans->sip_xaction_TA);
9552882Svi117747 				SIP_CANCEL_TIMER(
9562882Svi117747 				    sip_trans->sip_xaction_TB);
9572882Svi117747 				sip_trans->sip_xaction_state =
9582882Svi117747 				    SIP_CLNT_INV_TERMINATED;
9592882Svi117747 			} else if (SIP_NONOK_FINAL_RESP(resp_code)) {
9602882Svi117747 				int	ret;
9612882Svi117747 
9622882Svi117747 				/*
9632882Svi117747 				 * sip_trans->sip_xaction_last_msg ?
9642882Svi117747 				 */
9652882Svi117747 				SIP_CANCEL_TIMER(
9662882Svi117747 				    sip_trans->sip_xaction_TA);
9672882Svi117747 				SIP_CANCEL_TIMER(
9682882Svi117747 				    sip_trans->sip_xaction_TB);
9692882Svi117747 				if ((ret = sip_create_send_nonOKack(conn_obj,
9702882Svi117747 				    sip_trans, msg, B_FALSE)) != 0) {
9712882Svi117747 					(void) pthread_mutex_unlock(
9722882Svi117747 					    &sip_trans->sip_xaction_mutex);
9732882Svi117747 					return (ret);
9742882Svi117747 				}
9752882Svi117747 				/*
9762882Svi117747 				 * start timer D for unreliable transports
9772882Svi117747 				 */
9782882Svi117747 				if (!isreliable) {
9792882Svi117747 					timer_obj_D = sip_setup_timer(
9802882Svi117747 					    conn_obj, sip_trans,
9812882Svi117747 					    NULL, sip_trans->sip_xaction_TD,
9822882Svi117747 					    SIP_XACTION_TIMER_D);
9832882Svi117747 					if (timer_obj_D == NULL) {
9842882Svi117747 						(void) pthread_mutex_unlock(
9852882Svi117747 						    &sip_trans->
9862882Svi117747 						    sip_xaction_mutex);
9872882Svi117747 						return (ENOMEM);
9882882Svi117747 					}
9892882Svi117747 					SIP_SCHED_TIMER(
9902882Svi117747 					    sip_trans->sip_xaction_TD,
9912882Svi117747 					    timer_obj_D,
9922882Svi117747 					    sip_xaction_state_timer_fire);
9932882Svi117747 					if (!SIP_IS_TIMER_RUNNING(
9942882Svi117747 					    sip_trans->sip_xaction_TD)) {
9952882Svi117747 						(void) pthread_mutex_unlock(
9962882Svi117747 						    &sip_trans->
9972882Svi117747 						    sip_xaction_mutex);
9982882Svi117747 						free(timer_obj_D);
9992882Svi117747 						return (ENOMEM);
10002882Svi117747 					}
10012882Svi117747 					sip_trans->sip_xaction_state =
10022882Svi117747 					    SIP_CLNT_INV_COMPLETED;
10032882Svi117747 				} else {
10042882Svi117747 					sip_trans->sip_xaction_state =
10052882Svi117747 					    SIP_CLNT_INV_TERMINATED;
10062882Svi117747 				}
10072882Svi117747 			} else {
10082882Svi117747 				/*
10092882Svi117747 				 * Invalid resp_code
10102882Svi117747 				 */
10112882Svi117747 				(void) pthread_mutex_unlock(
10122882Svi117747 				    &sip_trans->sip_xaction_mutex);
10132882Svi117747 				return (EPROTO);
10142882Svi117747 			}
10152882Svi117747 			break;
10162882Svi117747 		case SIP_CLNT_INV_PROCEEDING:
10172882Svi117747 			if (SIP_PROVISIONAL_RESP(resp_code)) {
10182882Svi117747 				break;
10192882Svi117747 			} else if (SIP_OK_RESP(resp_code)) {
10202882Svi117747 				SIP_CANCEL_TIMER(
10212882Svi117747 				    sip_trans->sip_xaction_TB);
10222882Svi117747 				sip_trans->sip_xaction_state =
10232882Svi117747 				    SIP_CLNT_INV_TERMINATED;
10242882Svi117747 			} else if (SIP_NONOK_FINAL_RESP(resp_code)) {
10252882Svi117747 				int	ret;
10262882Svi117747 
10272882Svi117747 				SIP_CANCEL_TIMER(
10282882Svi117747 				    sip_trans->sip_xaction_TB);
10292882Svi117747 				if ((ret = sip_create_send_nonOKack(conn_obj,
10302882Svi117747 				    sip_trans, msg, B_FALSE)) != 0) {
10312882Svi117747 					(void) pthread_mutex_unlock(
10322882Svi117747 					    &sip_trans->sip_xaction_mutex);
10332882Svi117747 					return (ret);
10342882Svi117747 				}
10352882Svi117747 				/*
10362882Svi117747 				 * start timer D for unreliable transports
10372882Svi117747 				 */
10382882Svi117747 				if (!isreliable) {
10392882Svi117747 					timer_obj_D = sip_setup_timer(
10402882Svi117747 					    conn_obj, sip_trans,
10412882Svi117747 					    NULL, sip_trans->sip_xaction_TD,
10422882Svi117747 					    SIP_XACTION_TIMER_D);
10432882Svi117747 					if (timer_obj_D == NULL) {
10442882Svi117747 						(void) pthread_mutex_unlock(
10452882Svi117747 						    &sip_trans->
10462882Svi117747 						    sip_xaction_mutex);
10472882Svi117747 						return (ENOMEM);
10482882Svi117747 					}
10492882Svi117747 					SIP_SCHED_TIMER(
10502882Svi117747 					    sip_trans->sip_xaction_TD,
10512882Svi117747 					    timer_obj_D,
10522882Svi117747 					    sip_xaction_state_timer_fire);
10532882Svi117747 					if (!SIP_IS_TIMER_RUNNING(
10542882Svi117747 					    sip_trans->sip_xaction_TD)) {
10552882Svi117747 						(void) pthread_mutex_unlock(
10562882Svi117747 						    &sip_trans->
10572882Svi117747 						    sip_xaction_mutex);
10582882Svi117747 						free(timer_obj_D);
10592882Svi117747 						return (ENOMEM);
10602882Svi117747 					}
10612882Svi117747 					sip_trans->sip_xaction_state =
10622882Svi117747 					    SIP_CLNT_INV_COMPLETED;
10632882Svi117747 				} else {
10642882Svi117747 					sip_trans->sip_xaction_state =
10652882Svi117747 					    SIP_CLNT_INV_TERMINATED;
10662882Svi117747 				}
10672882Svi117747 			} else {
10682882Svi117747 				(void) pthread_mutex_unlock(
10692882Svi117747 				    &sip_trans->sip_xaction_mutex);
10702882Svi117747 				return (EPROTO);
10712882Svi117747 			}
10722882Svi117747 			break;
10732882Svi117747 		case SIP_CLNT_INV_COMPLETED:
10742882Svi117747 			/*
10752882Svi117747 			 * Transport error takes it to
10762882Svi117747 			 * SIP_CLNT_INV_TERMINATED
10772882Svi117747 			 */
10782882Svi117747 			if (SIP_NONOK_FINAL_RESP(resp_code)) {
10792882Svi117747 				int	ret;
10802882Svi117747 
10812882Svi117747 				if ((ret = sip_create_send_nonOKack(conn_obj,
10822882Svi117747 				    sip_trans, msg, B_FALSE)) != 0) {
10832882Svi117747 					(void) pthread_mutex_unlock(
10842882Svi117747 					    &sip_trans->sip_xaction_mutex);
10852882Svi117747 					return (ret);
10862882Svi117747 				}
10872882Svi117747 			} else {
10882882Svi117747 				/*
10892882Svi117747 				 * Invalid resp_code
10902882Svi117747 				 */
10912882Svi117747 				(void) pthread_mutex_unlock(
10922882Svi117747 				    &sip_trans->sip_xaction_mutex);
10932882Svi117747 				return (EPROTO);
10942882Svi117747 			}
10952882Svi117747 			break;
10962882Svi117747 		default:
10972882Svi117747 			(void) pthread_mutex_unlock(
10982882Svi117747 			    &sip_trans->sip_xaction_mutex);
10992882Svi117747 			return (EPROTO);
11002882Svi117747 	}
11012882Svi117747 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
11022882Svi117747 	if (prev_state != sip_trans->sip_xaction_state &&
11032882Svi117747 	    sip_xaction_ulp_state_cb != NULL) {
11042882Svi117747 		sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
11052882Svi117747 		    (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
11062882Svi117747 	}
11072882Svi117747 	return (0);
11082882Svi117747 }
11092882Svi117747 
11102882Svi117747 /*
11112882Svi117747  * Process a NON-INVITE Response
11122882Svi117747  */
11132882Svi117747 static int
sip_clnt_xaction_noninv_res(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t ** sip_msg)11142882Svi117747 sip_clnt_xaction_noninv_res(sip_conn_object_t conn_obj,
11152882Svi117747     sip_xaction_t *sip_trans, _sip_msg_t **sip_msg)
11162882Svi117747 {
11172882Svi117747 	int			resp_code;
11182882Svi117747 	sip_xaction_time_obj_t	*timer_obj_K = NULL;
11192882Svi117747 	sip_message_type_t	*sip_msg_info;
11202882Svi117747 	int			prev_state;
11212882Svi117747 	_sip_msg_t		*msg = *sip_msg;
11222882Svi117747 	boolean_t		isreliable;
11232882Svi117747 
1124*5842Sgm209912 	if (msg->sip_msg_req_res == NULL || sip_trans == NULL) {
1125*5842Sgm209912 		sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
1126*5842Sgm209912 		    SIP_ASSERT_ERROR, __FILE__, __LINE__);
1127*5842Sgm209912 	}
11282882Svi117747 	assert(msg->sip_msg_req_res != NULL);
11292882Svi117747 	assert(sip_trans != NULL);
11302882Svi117747 
11312882Svi117747 	sip_msg_info = msg->sip_msg_req_res;
11322882Svi117747 	isreliable = sip_is_conn_reliable(conn_obj);
11332882Svi117747 	resp_code = sip_msg_info->sip_resp_code;
11342882Svi117747 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
11352882Svi117747 	prev_state = sip_trans->sip_xaction_state;
11362882Svi117747 	switch (sip_trans->sip_xaction_state) {
11372882Svi117747 		case SIP_CLNT_TRYING:
11382882Svi117747 			if (SIP_PROVISIONAL_RESP(resp_code)) {
11392882Svi117747 				sip_trans->sip_xaction_state =
11402882Svi117747 				    SIP_CLNT_NONINV_PROCEEDING;
11412882Svi117747 			} else if (SIP_FINAL_RESP(resp_code)) {
11422882Svi117747 				SIP_CANCEL_TIMER(
11432882Svi117747 				    sip_trans->sip_xaction_TE);
11442882Svi117747 				SIP_CANCEL_TIMER(
11452882Svi117747 				    sip_trans->sip_xaction_TF);
11462882Svi117747 				/*
11472882Svi117747 				 * Start timer K for unreliable transports
11482882Svi117747 				 */
11492882Svi117747 				if (!isreliable) {
11502882Svi117747 					timer_obj_K = sip_setup_timer(
11512882Svi117747 					    conn_obj, sip_trans,
11522882Svi117747 					    NULL, sip_trans->sip_xaction_TK,
11532882Svi117747 					    SIP_XACTION_TIMER_K);
11542882Svi117747 					if (timer_obj_K == NULL) {
11552882Svi117747 						(void) pthread_mutex_unlock(&
11562882Svi117747 						    sip_trans->
11572882Svi117747 						    sip_xaction_mutex);
11582882Svi117747 						return (ENOMEM);
11592882Svi117747 					}
11602882Svi117747 					SIP_SCHED_TIMER(
11612882Svi117747 					    sip_trans->sip_xaction_TK,
11622882Svi117747 					    timer_obj_K,
11632882Svi117747 					    sip_xaction_state_timer_fire);
11642882Svi117747 					if (!SIP_IS_TIMER_RUNNING(
11652882Svi117747 					    sip_trans->sip_xaction_TK)) {
11662882Svi117747 						(void) pthread_mutex_unlock(
11672882Svi117747 						    &sip_trans->
11682882Svi117747 						    sip_xaction_mutex);
11692882Svi117747 						free(timer_obj_K);
11702882Svi117747 						return (ENOMEM);
11712882Svi117747 					}
11722882Svi117747 					sip_trans->sip_xaction_state =
11732882Svi117747 					    SIP_CLNT_NONINV_COMPLETED;
11742882Svi117747 				} else {
11752882Svi117747 					sip_trans->sip_xaction_state =
11762882Svi117747 					    SIP_CLNT_NONINV_TERMINATED;
11772882Svi117747 				}
11782882Svi117747 			}
11792882Svi117747 			break;
11802882Svi117747 		case SIP_CLNT_NONINV_PROCEEDING:
11812882Svi117747 			if (SIP_PROVISIONAL_RESP(resp_code)) {
11822882Svi117747 				break;
11832882Svi117747 			} else if (SIP_FINAL_RESP(resp_code)) {
11842882Svi117747 				SIP_CANCEL_TIMER(
11852882Svi117747 				    sip_trans->sip_xaction_TE);
11862882Svi117747 				SIP_CANCEL_TIMER(
11872882Svi117747 				    sip_trans->sip_xaction_TF);
11882882Svi117747 				/*
11892882Svi117747 				 * Start timer K for unreliable transports
11902882Svi117747 				 */
11912882Svi117747 				if (!isreliable) {
11922882Svi117747 					timer_obj_K = sip_setup_timer(
11932882Svi117747 					    conn_obj, sip_trans,
11942882Svi117747 					    NULL, sip_trans->sip_xaction_TK,
11952882Svi117747 					    SIP_XACTION_TIMER_K);
11962882Svi117747 					if (timer_obj_K == NULL) {
11972882Svi117747 						(void) pthread_mutex_unlock(&
11982882Svi117747 						    sip_trans->
11992882Svi117747 						    sip_xaction_mutex);
12002882Svi117747 						return (ENOMEM);
12012882Svi117747 					}
12022882Svi117747 					SIP_SCHED_TIMER(
12032882Svi117747 					    sip_trans->sip_xaction_TK,
12042882Svi117747 					    timer_obj_K,
12052882Svi117747 					    sip_xaction_state_timer_fire);
12062882Svi117747 					if (!SIP_IS_TIMER_RUNNING(
12072882Svi117747 					    sip_trans->sip_xaction_TK)) {
12082882Svi117747 						(void) pthread_mutex_unlock(
12092882Svi117747 						    &sip_trans->
12102882Svi117747 						    sip_xaction_mutex);
12112882Svi117747 						free(timer_obj_K);
12122882Svi117747 						return (ENOMEM);
12132882Svi117747 					}
12142882Svi117747 					sip_trans->sip_xaction_state =
12152882Svi117747 					    SIP_CLNT_NONINV_COMPLETED;
12162882Svi117747 				} else {
12172882Svi117747 					sip_trans->sip_xaction_state =
12182882Svi117747 					    SIP_CLNT_NONINV_TERMINATED;
12192882Svi117747 				}
12202882Svi117747 			}
12212882Svi117747 			break;
12222882Svi117747 		default:
12232882Svi117747 			(void) pthread_mutex_unlock(
12242882Svi117747 			    &sip_trans->sip_xaction_mutex);
12252882Svi117747 			return (EPROTO);
12262882Svi117747 	}
12272882Svi117747 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
12282882Svi117747 	if (prev_state != sip_trans->sip_xaction_state &&
12292882Svi117747 	    sip_xaction_ulp_state_cb != NULL) {
12302882Svi117747 		sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
12312882Svi117747 		    (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
12322882Svi117747 	}
12332882Svi117747 	return (0);
12342882Svi117747 }
12352882Svi117747 
12362882Svi117747 /*
12372882Svi117747  * If there is a transport error, sending the message out, terminate the
12382882Svi117747  * transaction.
12392882Svi117747  */
12402882Svi117747 /* ARGSUSED */
12412882Svi117747 void
sip_xaction_terminate(sip_xaction_t * sip_trans,_sip_msg_t * msg,int transport)12422882Svi117747 sip_xaction_terminate(sip_xaction_t *sip_trans, _sip_msg_t *msg, int transport)
12432882Svi117747 {
12442882Svi117747 	sip_message_type_t	*sip_msg_info;
12452882Svi117747 	int			state;
12462882Svi117747 	int			prev_state;
12472882Svi117747 
12482882Svi117747 	sip_msg_info = msg->sip_msg_req_res;
12492882Svi117747 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
12502882Svi117747 	if (sip_msg_info->is_request) {
12512882Svi117747 		if (sip_trans->sip_xaction_method == INVITE)
12522882Svi117747 			state = SIP_CLNT_INV_TERMINATED;
12532882Svi117747 		else
12542882Svi117747 			state = SIP_CLNT_NONINV_TERMINATED;
12552882Svi117747 	} else {
12562882Svi117747 		if (sip_trans->sip_xaction_method == INVITE)
12572882Svi117747 			state = SIP_SRV_INV_TERMINATED;
12582882Svi117747 		else
12592882Svi117747 			state = SIP_SRV_NONINV_TERMINATED;
12602882Svi117747 	}
12612882Svi117747 	prev_state = sip_trans->sip_xaction_state;
12622882Svi117747 	sip_trans->sip_xaction_state = state;
12632882Svi117747 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
12642882Svi117747 	if (sip_xaction_ulp_state_cb != NULL) {
12652882Svi117747 		sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
12662882Svi117747 		    (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
12672882Svi117747 	}
12682882Svi117747 	sip_xaction_delete(sip_trans);
12692882Svi117747 }
12702882Svi117747 
12712882Svi117747 /*
12722882Svi117747  * --------------------------- Timer Routine ---------------------------
12732882Svi117747  */
12742882Svi117747 
12752882Svi117747 void
sip_xaction_state_timer_fire(void * args)12762882Svi117747 sip_xaction_state_timer_fire(void *args)
12772882Svi117747 {
12782882Svi117747 	sip_xaction_time_obj_t	*time_obj = (sip_xaction_time_obj_t *)args;
12792882Svi117747 	sip_xaction_t		*sip_trans = time_obj->sip_trans;
12802882Svi117747 	_sip_msg_t		*new_msg;
12812882Svi117747 	boolean_t		destroy_trans = B_FALSE;
12822882Svi117747 	sip_conn_object_t	conn_obj;
12832882Svi117747 	int			prev_state;
1284*5842Sgm209912 	sip_message_type_t	*msg_info;
1285*5842Sgm209912 	int			resp;
1286*5842Sgm209912 	sip_method_t		method;
12872882Svi117747 
12882882Svi117747 	assert(time_obj != NULL);
12892882Svi117747 
12902882Svi117747 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
12912882Svi117747 	prev_state = sip_trans->sip_xaction_state;
12922882Svi117747 	switch (time_obj->sip_xaction_timer_type) {
12932882Svi117747 		case SIP_XACTION_TIMER_A:
12942882Svi117747 			if (sip_trans->sip_xaction_state != SIP_CLNT_CALLING)
12952882Svi117747 				break;
12962882Svi117747 			/*
12972882Svi117747 			 * Assert candidate
12982882Svi117747 			 */
12992882Svi117747 			if (sip_trans->sip_xaction_last_msg == NULL)
13002882Svi117747 				break;
13012882Svi117747 			if (sip_trans->sip_xaction_conn_obj == NULL)
13022882Svi117747 				break;
13032882Svi117747 			new_msg = sip_trans->sip_xaction_last_msg;
13042882Svi117747 			conn_obj = sip_trans->sip_xaction_conn_obj;
1305*5842Sgm209912 			/* timer A is for INVITE-RETRANSMIT only */
1306*5842Sgm209912 			SIP_UPDATE_COUNTERS(B_TRUE, INVITE, 0, B_TRUE, new_msg->
1307*5842Sgm209912 			    sip_msg_len);
1308*5842Sgm209912 			++sip_trans->sip_xaction_msgcnt;
1309*5842Sgm209912 			sip_add_log(&sip_trans->sip_xaction_log[sip_trans->
1310*5842Sgm209912 			    sip_xaction_state], new_msg, sip_trans->
1311*5842Sgm209912 			    sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
13122882Svi117747 			if (sip_stack_send(conn_obj, new_msg->sip_msg_buf,
13132882Svi117747 			    new_msg->sip_msg_len) != 0) {
13142882Svi117747 				sip_del_conn_obj_cache(
13152882Svi117747 				    sip_trans->sip_xaction_conn_obj,
13162882Svi117747 				    (void *)sip_trans);
13172882Svi117747 				sip_trans->sip_xaction_state =
13182882Svi117747 				    SIP_CLNT_INV_TERMINATED;
13192882Svi117747 				(void) pthread_mutex_unlock(
13202882Svi117747 				    &sip_trans->sip_xaction_mutex);
13212882Svi117747 				if (sip_xaction_ulp_state_cb != NULL) {
1322*5842Sgm209912 					sip_xaction_ulp_state_cb(
1323*5842Sgm209912 					    (sip_transaction_t)sip_trans, NULL,
1324*5842Sgm209912 					    prev_state, sip_trans->
1325*5842Sgm209912 					    sip_xaction_state);
13262882Svi117747 				}
13272882Svi117747 				if (sip_xaction_ulp_trans_err != NULL) {
13282882Svi117747 					sip_xaction_ulp_trans_err(sip_trans, 0,
13292882Svi117747 					    NULL);
13302882Svi117747 				}
13312882Svi117747 				sip_xaction_delete(sip_trans);
13322882Svi117747 				free(time_obj);
13332882Svi117747 				return;
13342882Svi117747 			}
13352882Svi117747 			SIP_SET_TIMEOUT(sip_trans->sip_xaction_TA,
13362882Svi117747 			    2 * SIP_GET_TIMEOUT(sip_trans->sip_xaction_TA));
13372882Svi117747 			/*
13382882Svi117747 			 * Reschedule the timer
13392882Svi117747 			 */
13402882Svi117747 			SIP_SCHED_TIMER(sip_trans->sip_xaction_TA,
13412882Svi117747 			    time_obj, sip_xaction_state_timer_fire);
13422882Svi117747 			if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TA)) {
13432882Svi117747 				sip_del_conn_obj_cache(
13442882Svi117747 				    sip_trans->sip_xaction_conn_obj,
13452882Svi117747 				    (void *)sip_trans);
13462882Svi117747 				sip_trans->sip_xaction_state =
13472882Svi117747 				    SIP_CLNT_INV_TERMINATED;
13482882Svi117747 				(void) pthread_mutex_unlock(
13492882Svi117747 				    &sip_trans->sip_xaction_mutex);
13502882Svi117747 				if (sip_xaction_ulp_state_cb != NULL) {
1351*5842Sgm209912 					sip_xaction_ulp_state_cb(
1352*5842Sgm209912 					    (sip_transaction_t)sip_trans, NULL,
1353*5842Sgm209912 					    prev_state, sip_trans->
1354*5842Sgm209912 					    sip_xaction_state);
13552882Svi117747 				}
13562882Svi117747 				if (sip_xaction_ulp_trans_err != NULL) {
13572882Svi117747 					sip_xaction_ulp_trans_err(sip_trans, 0,
13582882Svi117747 					    NULL);
13592882Svi117747 				}
13602882Svi117747 				sip_xaction_delete(sip_trans);
13612882Svi117747 				free(time_obj);
13622882Svi117747 				return;
13632882Svi117747 			}
13642882Svi117747 			(void) pthread_mutex_unlock(
13652882Svi117747 			    &sip_trans->sip_xaction_mutex);
13662882Svi117747 			return;
13672882Svi117747 		case SIP_XACTION_TIMER_B:
13682882Svi117747 			SIP_CANCEL_TIMER(sip_trans->sip_xaction_TA);
13692882Svi117747 			if (sip_trans->sip_xaction_state == SIP_CLNT_CALLING) {
13702882Svi117747 				sip_trans->sip_xaction_state =
13712882Svi117747 				    SIP_CLNT_INV_TERMINATED;
13722882Svi117747 				(void) pthread_mutex_unlock(
13732882Svi117747 				    &sip_trans->sip_xaction_mutex);
13742882Svi117747 				if (sip_xaction_ulp_state_cb != NULL) {
1375*5842Sgm209912 					sip_xaction_ulp_state_cb(
1376*5842Sgm209912 					    (sip_transaction_t)sip_trans, NULL,
1377*5842Sgm209912 					    prev_state, sip_trans->
1378*5842Sgm209912 					    sip_xaction_state);
13792882Svi117747 				}
13802882Svi117747 				if (sip_xaction_ulp_trans_err != NULL) {
13812882Svi117747 					sip_xaction_ulp_trans_err(sip_trans, 0,
13822882Svi117747 					    NULL);
13832882Svi117747 				}
13842882Svi117747 				sip_xaction_delete(sip_trans);
13852882Svi117747 				free(time_obj);
13862882Svi117747 				return;
13872882Svi117747 			}
13882882Svi117747 			break;
13892882Svi117747 		case SIP_XACTION_TIMER_D:
13902882Svi117747 			if (sip_trans->sip_xaction_state ==
13912882Svi117747 			    SIP_CLNT_INV_COMPLETED) {
13922882Svi117747 				SIP_CANCEL_TIMER(
13932882Svi117747 				    sip_trans->sip_xaction_TB);
13942882Svi117747 				sip_trans->sip_xaction_state =
13952882Svi117747 				    SIP_CLNT_INV_TERMINATED;
13962882Svi117747 				destroy_trans = B_TRUE;
13972882Svi117747 			}
13982882Svi117747 			break;
13992882Svi117747 		case SIP_XACTION_TIMER_E:
14002882Svi117747 			/*
14012882Svi117747 			 * Assert candidate
14022882Svi117747 			 */
14032882Svi117747 			if (sip_trans->sip_xaction_state != SIP_CLNT_TRYING &&
14042882Svi117747 			    sip_trans->sip_xaction_state !=
14052882Svi117747 			    SIP_CLNT_NONINV_PROCEEDING) {
14062882Svi117747 				break;
14072882Svi117747 			}
14082882Svi117747 			/*
14092882Svi117747 			 * Assert candidate
14102882Svi117747 			 */
14112882Svi117747 			if (sip_trans->sip_xaction_last_msg == NULL)
14122882Svi117747 				break;
14132882Svi117747 			if (sip_trans->sip_xaction_conn_obj == NULL)
14142882Svi117747 				break;
14152882Svi117747 			conn_obj = sip_trans->sip_xaction_conn_obj;
14162882Svi117747 			new_msg = sip_trans->sip_xaction_last_msg;
1417*5842Sgm209912 			/* Timer E is for non-INVITE request */
1418*5842Sgm209912 
1419*5842Sgm209912 			msg_info = new_msg->sip_msg_req_res;
1420*5842Sgm209912 			if (msg_info == NULL || !msg_info->is_request) {
1421*5842Sgm209912 				(void) sip_write_to_log((void *) sip_trans,
1422*5842Sgm209912 				    SIP_TRANSACTION_LOG | SIP_ASSERT_ERROR,
1423*5842Sgm209912 				    __FILE__, __LINE__);
1424*5842Sgm209912 			}
1425*5842Sgm209912 			assert(msg_info != NULL && msg_info->is_request);
1426*5842Sgm209912 			method = msg_info->sip_req_method;
1427*5842Sgm209912 			SIP_UPDATE_COUNTERS(B_TRUE, method, 0, B_TRUE, new_msg->
1428*5842Sgm209912 			    sip_msg_len);
1429*5842Sgm209912 			++sip_trans->sip_xaction_msgcnt;
1430*5842Sgm209912 			sip_add_log(&sip_trans->sip_xaction_log[sip_trans->
1431*5842Sgm209912 			    sip_xaction_state], new_msg, sip_trans->
1432*5842Sgm209912 			    sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
14332882Svi117747 			if (sip_stack_send(conn_obj, new_msg->sip_msg_buf,
14342882Svi117747 			    new_msg->sip_msg_len) != 0) {
14352882Svi117747 				sip_del_conn_obj_cache(
14362882Svi117747 				    sip_trans->sip_xaction_conn_obj,
14372882Svi117747 				    (void *)sip_trans);
14382882Svi117747 				sip_trans->sip_xaction_state =
14392882Svi117747 				    SIP_CLNT_NONINV_TERMINATED;
14402882Svi117747 				(void) pthread_mutex_unlock(
14412882Svi117747 				    &sip_trans->sip_xaction_mutex);
14422882Svi117747 				if (sip_xaction_ulp_state_cb != NULL) {
1443*5842Sgm209912 					sip_xaction_ulp_state_cb(
1444*5842Sgm209912 					    (sip_transaction_t)sip_trans, NULL,
1445*5842Sgm209912 					    prev_state, sip_trans->
1446*5842Sgm209912 					    sip_xaction_state);
14472882Svi117747 				}
14482882Svi117747 				if (sip_xaction_ulp_trans_err != NULL) {
14492882Svi117747 					sip_xaction_ulp_trans_err(sip_trans, 0,
14502882Svi117747 					    NULL);
14512882Svi117747 				}
14522882Svi117747 				sip_xaction_delete(sip_trans);
14532882Svi117747 				free(time_obj);
14542882Svi117747 				return;
14552882Svi117747 			}
14562882Svi117747 			SIP_SET_TIMEOUT(sip_trans->sip_xaction_TE,
14572882Svi117747 			    MIN(SIP_TIMER_T2,
14582882Svi117747 			    2 * SIP_GET_TIMEOUT(sip_trans->sip_xaction_TE)));
14592882Svi117747 			/*
14602882Svi117747 			 * Reschedule the timer
14612882Svi117747 			 */
14622882Svi117747 			SIP_SCHED_TIMER(sip_trans->sip_xaction_TE,
14632882Svi117747 			    time_obj, sip_xaction_state_timer_fire);
14642882Svi117747 			if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TE)) {
14652882Svi117747 				sip_del_conn_obj_cache(
14662882Svi117747 				    sip_trans->sip_xaction_conn_obj,
14672882Svi117747 				    (void *)sip_trans);
14682882Svi117747 				sip_trans->sip_xaction_state =
14692882Svi117747 				    SIP_CLNT_NONINV_TERMINATED;
14702882Svi117747 				(void) pthread_mutex_unlock(
14712882Svi117747 				    &sip_trans->sip_xaction_mutex);
14722882Svi117747 				if (sip_xaction_ulp_state_cb != NULL) {
1473*5842Sgm209912 					sip_xaction_ulp_state_cb(
1474*5842Sgm209912 					    (sip_transaction_t)sip_trans, NULL,
1475*5842Sgm209912 					    prev_state, sip_trans->
1476*5842Sgm209912 					    sip_xaction_state);
14772882Svi117747 				}
14782882Svi117747 				if (sip_xaction_ulp_trans_err != NULL) {
14792882Svi117747 					sip_xaction_ulp_trans_err(sip_trans, 0,
14802882Svi117747 					    NULL);
14812882Svi117747 				}
14822882Svi117747 				sip_xaction_delete(sip_trans);
14832882Svi117747 				free(time_obj);
14842882Svi117747 				return;
14852882Svi117747 			}
14862882Svi117747 			(void) pthread_mutex_unlock(
14872882Svi117747 			    &sip_trans->sip_xaction_mutex);
14882882Svi117747 			return;
14892882Svi117747 		case SIP_XACTION_TIMER_F:
14902882Svi117747 			SIP_CANCEL_TIMER(sip_trans->sip_xaction_TE);
14912882Svi117747 			if (sip_trans->sip_xaction_state == SIP_CLNT_TRYING ||
14922882Svi117747 			    sip_trans->sip_xaction_state ==
14932882Svi117747 			    SIP_CLNT_NONINV_PROCEEDING) {
14942882Svi117747 				sip_trans->sip_xaction_state =
14952882Svi117747 				    SIP_CLNT_NONINV_TERMINATED;
14962882Svi117747 				(void) pthread_mutex_unlock(
14972882Svi117747 				    &sip_trans->sip_xaction_mutex);
14982882Svi117747 				if (sip_xaction_ulp_state_cb != NULL) {
1499*5842Sgm209912 					sip_xaction_ulp_state_cb(
1500*5842Sgm209912 					    (sip_transaction_t)sip_trans, NULL,
1501*5842Sgm209912 					    prev_state, sip_trans->
1502*5842Sgm209912 					    sip_xaction_state);
15032882Svi117747 				}
15042882Svi117747 				if (sip_xaction_ulp_trans_err != NULL) {
15052882Svi117747 					sip_xaction_ulp_trans_err(sip_trans, 0,
15062882Svi117747 					    NULL);
15072882Svi117747 				}
15082882Svi117747 				sip_xaction_delete(sip_trans);
15092882Svi117747 				free(time_obj);
15102882Svi117747 				return;
15112882Svi117747 			}
15122882Svi117747 			break;
15132882Svi117747 		case SIP_XACTION_TIMER_G:
15142882Svi117747 			/*
15152882Svi117747 			 * Assert candidate
15162882Svi117747 			 */
15172882Svi117747 			if (sip_trans->sip_xaction_last_msg == NULL)
15182882Svi117747 				break;
15192882Svi117747 			if (sip_trans->sip_xaction_conn_obj == NULL)
15202882Svi117747 				break;
15212882Svi117747 			if (sip_trans->sip_xaction_state !=
15222882Svi117747 			    SIP_SRV_INV_COMPLETED) {
15232882Svi117747 				break;
15242882Svi117747 			}
15252882Svi117747 			new_msg = sip_trans->sip_xaction_last_msg;
15262882Svi117747 			conn_obj = sip_trans->sip_xaction_conn_obj;
1527*5842Sgm209912 			msg_info = new_msg->sip_msg_req_res;
1528*5842Sgm209912 			if (msg_info == NULL || msg_info->is_request) {
1529*5842Sgm209912 				(void) sip_write_to_log((void *) sip_trans,
1530*5842Sgm209912 				    SIP_TRANSACTION_LOG | SIP_ASSERT_ERROR,
1531*5842Sgm209912 				    __FILE__, __LINE__);
1532*5842Sgm209912 			}
1533*5842Sgm209912 			assert(msg_info != NULL && !msg_info->is_request);
1534*5842Sgm209912 			resp = msg_info->sip_resp_code;
1535*5842Sgm209912 			SIP_UPDATE_COUNTERS(B_FALSE, 0, resp, B_TRUE, new_msg->
1536*5842Sgm209912 			    sip_msg_len);
1537*5842Sgm209912 			++sip_trans->sip_xaction_msgcnt;
1538*5842Sgm209912 			sip_add_log(&sip_trans->sip_xaction_log[sip_trans->
1539*5842Sgm209912 			    sip_xaction_state], new_msg, sip_trans->
1540*5842Sgm209912 			    sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
15412882Svi117747 			if (sip_stack_send(conn_obj, new_msg->sip_msg_buf,
15422882Svi117747 			    new_msg->sip_msg_len) != 0) {
15432882Svi117747 				sip_del_conn_obj_cache(
15442882Svi117747 				    sip_trans->sip_xaction_conn_obj,
15452882Svi117747 				    (void *)sip_trans);
15462882Svi117747 				sip_trans->sip_xaction_state =
15472882Svi117747 				    SIP_SRV_INV_TERMINATED;
15482882Svi117747 				(void) pthread_mutex_unlock(
15492882Svi117747 				    &sip_trans->sip_xaction_mutex);
15502882Svi117747 				if (sip_xaction_ulp_state_cb != NULL) {
1551*5842Sgm209912 					sip_xaction_ulp_state_cb(
1552*5842Sgm209912 					    (sip_transaction_t)sip_trans, NULL,
1553*5842Sgm209912 					    prev_state, sip_trans->
1554*5842Sgm209912 					    sip_xaction_state);
15552882Svi117747 				}
15562882Svi117747 				if (sip_xaction_ulp_trans_err != NULL) {
15572882Svi117747 					sip_xaction_ulp_trans_err(sip_trans, 0,
15582882Svi117747 					    NULL);
15592882Svi117747 				}
15602882Svi117747 				sip_xaction_delete(sip_trans);
15612882Svi117747 				free(time_obj);
15622882Svi117747 				return;
15632882Svi117747 			}
15642882Svi117747 			SIP_SET_TIMEOUT(sip_trans->sip_xaction_TG,
15652882Svi117747 			    MIN(SIP_TIMER_T2,
15662882Svi117747 			    2 * SIP_GET_TIMEOUT(sip_trans->sip_xaction_TG)));
15672882Svi117747 			SIP_SCHED_TIMER(sip_trans->sip_xaction_TG,
15682882Svi117747 			    time_obj, sip_xaction_state_timer_fire);
15692882Svi117747 			if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TG)) {
15702882Svi117747 				sip_del_conn_obj_cache(
15712882Svi117747 				    sip_trans->sip_xaction_conn_obj,
15722882Svi117747 				    (void *)sip_trans);
15732882Svi117747 				sip_trans->sip_xaction_state =
15742882Svi117747 				    SIP_SRV_INV_TERMINATED;
15752882Svi117747 				(void) pthread_mutex_unlock(
15762882Svi117747 				    &sip_trans->sip_xaction_mutex);
15772882Svi117747 				if (sip_xaction_ulp_state_cb != NULL) {
1578*5842Sgm209912 					sip_xaction_ulp_state_cb(
1579*5842Sgm209912 					    (sip_transaction_t)sip_trans, NULL,
1580*5842Sgm209912 					    prev_state, sip_trans->
1581*5842Sgm209912 					    sip_xaction_state);
15822882Svi117747 				}
15832882Svi117747 				if (sip_xaction_ulp_trans_err != NULL) {
15842882Svi117747 					sip_xaction_ulp_trans_err(sip_trans, 0,
15852882Svi117747 					    NULL);
15862882Svi117747 				}
15872882Svi117747 				sip_xaction_delete(sip_trans);
15882882Svi117747 				free(time_obj);
15892882Svi117747 				return;
15902882Svi117747 			}
15912882Svi117747 			(void) pthread_mutex_unlock(
15922882Svi117747 			    &sip_trans->sip_xaction_mutex);
15932882Svi117747 			return;
15942882Svi117747 		case SIP_XACTION_TIMER_H:
15952882Svi117747 			SIP_CANCEL_TIMER(sip_trans->sip_xaction_TG);
15962882Svi117747 			if (sip_trans->sip_xaction_state ==
15972882Svi117747 			    SIP_SRV_INV_COMPLETED) {
15982882Svi117747 				sip_trans->sip_xaction_state =
15992882Svi117747 				    SIP_SRV_INV_TERMINATED;
16002882Svi117747 				(void) pthread_mutex_unlock(
16012882Svi117747 				    &sip_trans->sip_xaction_mutex);
16022882Svi117747 				if (sip_xaction_ulp_state_cb != NULL) {
1603*5842Sgm209912 					sip_xaction_ulp_state_cb(
1604*5842Sgm209912 					    (sip_transaction_t)sip_trans, NULL,
1605*5842Sgm209912 					    prev_state, sip_trans->
1606*5842Sgm209912 					    sip_xaction_state);
16072882Svi117747 				}
16082882Svi117747 				if (sip_xaction_ulp_trans_err != NULL) {
16092882Svi117747 					sip_xaction_ulp_trans_err(sip_trans, 0,
16102882Svi117747 					    NULL);
16112882Svi117747 				}
16122882Svi117747 				sip_xaction_delete(sip_trans);
16132882Svi117747 				free(time_obj);
16142882Svi117747 				return;
16152882Svi117747 			}
16162882Svi117747 			break;
16172882Svi117747 		case SIP_XACTION_TIMER_I:
16182882Svi117747 			if (sip_trans->sip_xaction_state ==
16192882Svi117747 			    SIP_SRV_CONFIRMED) {
16202882Svi117747 				SIP_CANCEL_TIMER(
16212882Svi117747 				    sip_trans->sip_xaction_TH);
16222882Svi117747 				sip_trans->sip_xaction_state =
16232882Svi117747 				    SIP_SRV_INV_TERMINATED;
16242882Svi117747 				destroy_trans = B_TRUE;
16252882Svi117747 			}
16262882Svi117747 			break;
16272882Svi117747 		case SIP_XACTION_TIMER_J:
16282882Svi117747 			if (sip_trans->sip_xaction_state ==
16292882Svi117747 			    SIP_SRV_NONINV_COMPLETED) {
16302882Svi117747 				sip_trans->sip_xaction_state =
16312882Svi117747 				    SIP_SRV_NONINV_TERMINATED;
16322882Svi117747 				destroy_trans = B_TRUE;
16332882Svi117747 
16342882Svi117747 			}
16352882Svi117747 			break;
16362882Svi117747 		case SIP_XACTION_TIMER_K:
16372882Svi117747 			if (sip_trans->sip_xaction_state ==
16382882Svi117747 			    SIP_CLNT_NONINV_COMPLETED) {
16392882Svi117747 				SIP_CANCEL_TIMER(
16402882Svi117747 				    sip_trans->sip_xaction_TF);
16412882Svi117747 				sip_trans->sip_xaction_state =
16422882Svi117747 				    SIP_CLNT_NONINV_TERMINATED;
16432882Svi117747 				destroy_trans = B_TRUE;
16442882Svi117747 			}
16452882Svi117747 			break;
16462882Svi117747 		default:
16472882Svi117747 			break;
16482882Svi117747 	}
16492882Svi117747 	if (destroy_trans) {
16502882Svi117747 		(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
16512882Svi117747 		if (sip_xaction_ulp_state_cb != NULL &&
16522882Svi117747 		    prev_state != sip_trans->sip_xaction_state) {
16532882Svi117747 			sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
16542882Svi117747 			    NULL, prev_state, sip_trans->sip_xaction_state);
16552882Svi117747 		}
16562882Svi117747 		sip_xaction_delete(sip_trans);
16572882Svi117747 		free(time_obj);
16582882Svi117747 		return;
16592882Svi117747 	}
16602882Svi117747 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
16612882Svi117747 	if (sip_xaction_ulp_state_cb != NULL &&
16622882Svi117747 	    prev_state != sip_trans->sip_xaction_state) {
16632882Svi117747 		sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans, NULL,
16642882Svi117747 		    prev_state, sip_trans->sip_xaction_state);
16652882Svi117747 	}
16662882Svi117747 	free(time_obj);
16672882Svi117747 }
1668