140cb5e5dSvi /*
240cb5e5dSvi  * CDDL HEADER START
340cb5e5dSvi  *
440cb5e5dSvi  * The contents of this file are subject to the terms of the
540cb5e5dSvi  * Common Development and Distribution License (the "License").
640cb5e5dSvi  * You may not use this file except in compliance with the License.
740cb5e5dSvi  *
840cb5e5dSvi  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
940cb5e5dSvi  * or http://www.opensolaris.org/os/licensing.
1040cb5e5dSvi  * See the License for the specific language governing permissions
1140cb5e5dSvi  * and limitations under the License.
1240cb5e5dSvi  *
1340cb5e5dSvi  * When distributing Covered Code, include this CDDL HEADER in each
1440cb5e5dSvi  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1540cb5e5dSvi  * If applicable, add the following below this CDDL HEADER, with the
1640cb5e5dSvi  * fields enclosed by brackets "[]" replaced with your own identifying
1740cb5e5dSvi  * information: Portions Copyright [yyyy] [name of copyright owner]
1840cb5e5dSvi  *
1940cb5e5dSvi  * CDDL HEADER END
2040cb5e5dSvi  */
2140cb5e5dSvi 
2240cb5e5dSvi /*
23*943efbc3Sgm  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
2440cb5e5dSvi  * Use is subject to license terms.
2540cb5e5dSvi  */
2640cb5e5dSvi 
2740cb5e5dSvi /*
2840cb5e5dSvi  * SIP Client/Server Invite/Non-Invite Transaction State machine.
2940cb5e5dSvi  */
3040cb5e5dSvi 
312c2c4183Svi #include <stdlib.h>
322c2c4183Svi #include <string.h>
332c2c4183Svi #include <assert.h>
342c2c4183Svi #include <errno.h>
352c2c4183Svi #include <pthread.h>
362c2c4183Svi #include <sip.h>
372c2c4183Svi 
3840cb5e5dSvi #include "sip_miscdefs.h"
392c2c4183Svi #include "sip_msg.h"
4040cb5e5dSvi #include "sip_xaction.h"
4140cb5e5dSvi 
4240cb5e5dSvi /*
4340cb5e5dSvi  * Some Timer related info from RFC 3261, page 265.
4440cb5e5dSvi  *
4540cb5e5dSvi  * ----------------------------------------------------------------------
4640cb5e5dSvi  * Timer    Value            Section               Meaning
4740cb5e5dSvi  * ----------------------------------------------------------------------
4840cb5e5dSvi  * T1       500ms default    Section 17.1.1.1     RTT Estimate
4940cb5e5dSvi  * T2       4s               Section 17.1.2.2     The maximum retransmit
5040cb5e5dSvi  *                                                interval for non-INVITE
5140cb5e5dSvi  *                                                requests and INVITE
5240cb5e5dSvi  *                                                responses
5340cb5e5dSvi  * T4       5s               Section 17.1.2.2     Maximum duration a
5440cb5e5dSvi  *                                                message will
5540cb5e5dSvi  *                                                remain in the network
5640cb5e5dSvi  * ----------------------------------------------------------------------
5740cb5e5dSvi  * Timer A  initially T1     Section 17.1.1.2     INVITE request retransmit
5840cb5e5dSvi  *                                                interval, for UDP only
5940cb5e5dSvi  * Timer B  64*T1            Section 17.1.1.2     INVITE transaction
6040cb5e5dSvi  *                                                timeout timer
6140cb5e5dSvi  * Timer C  > 3min           Section 16.6         proxy INVITE transaction
6240cb5e5dSvi  *                            bullet 11            timeout
6340cb5e5dSvi  * Timer D  > 32s for UDP    Section 17.1.1.2     Wait time for response
6440cb5e5dSvi  *          0s for TCP/SCTP                       retransmits
6540cb5e5dSvi  * Timer E  initially T1     Section 17.1.2.2     non-INVITE request
6640cb5e5dSvi  *                                                retransmit interval,
6740cb5e5dSvi  *                                                UDP only
6840cb5e5dSvi  * Timer F  64*T1            Section 17.1.2.2     non-INVITE transaction
6940cb5e5dSvi  *                                                timeout timer
7040cb5e5dSvi  * Timer G  initially T1     Section 17.2.1       INVITE response
7140cb5e5dSvi  *                                                retransmit interval
7240cb5e5dSvi  * Timer H  64*T1            Section 17.2.1       Wait time for
7340cb5e5dSvi  *                                                ACK receipt
7440cb5e5dSvi  * Timer I  T4 for UDP       Section 17.2.1       Wait time for
7540cb5e5dSvi  *          0s for TCP/SCTP                       ACK retransmits
7640cb5e5dSvi  * Timer J  64*T1 for UDP    Section 17.2.2       Wait time for
7740cb5e5dSvi  *          0s for TCP/SCTP                       non-INVITE request
7840cb5e5dSvi  *                                                retransmits
7940cb5e5dSvi  * Timer K  T4 for UDP       Section 17.1.2.2     Wait time for
8040cb5e5dSvi  *          0s for TCP/SCTP                       response retransmits
8140cb5e5dSvi  * ----------------------------------------------------------------------
8240cb5e5dSvi  */
8340cb5e5dSvi 
8440cb5e5dSvi #ifndef MIN
8540cb5e5dSvi #define	MIN(a, b)	(((a) < (b)) ? (a):(b))
8640cb5e5dSvi #endif
8740cb5e5dSvi 
8840cb5e5dSvi /*
8940cb5e5dSvi  * Arg to the timer fire routine
9040cb5e5dSvi  */
9140cb5e5dSvi typedef	struct sip_xaction_timer_obj_s {
9240cb5e5dSvi 	sip_xaction_timer_type_t	sip_xaction_timer_type;
9340cb5e5dSvi 	sip_xaction_t			*sip_trans;
9440cb5e5dSvi 	int				sip_xaction_timer_xport;
9540cb5e5dSvi } sip_xaction_time_obj_t;
9640cb5e5dSvi 
9740cb5e5dSvi int		sip_xaction_output(sip_conn_object_t, sip_xaction_t *,
9840cb5e5dSvi 		    _sip_msg_t *);
9940cb5e5dSvi int		sip_xaction_input(sip_conn_object_t, sip_xaction_t *,
10040cb5e5dSvi 		    _sip_msg_t **);
10140cb5e5dSvi void		sip_xaction_terminate(sip_xaction_t *, _sip_msg_t *, int);
10240cb5e5dSvi 
10340cb5e5dSvi static int 	sip_clnt_xaction_output(sip_conn_object_t, sip_xaction_t *,
10440cb5e5dSvi 		    _sip_msg_t *);
10540cb5e5dSvi static int	sip_clnt_xaction_input(sip_conn_object_t, sip_xaction_t *,
10640cb5e5dSvi 		    _sip_msg_t **);
10740cb5e5dSvi static int	sip_clnt_xaction_inv_res(sip_conn_object_t, sip_xaction_t *,
10840cb5e5dSvi 		    _sip_msg_t **);
10940cb5e5dSvi static int	sip_clnt_xaction_noninv_res(sip_conn_object_t, sip_xaction_t *,
11040cb5e5dSvi 		    _sip_msg_t **);
11140cb5e5dSvi static int 	sip_srv_xaction_output(sip_conn_object_t, sip_xaction_t *,
11240cb5e5dSvi 		    _sip_msg_t *);
11340cb5e5dSvi static int	sip_srv_xaction_input(sip_conn_object_t, sip_xaction_t *,
11440cb5e5dSvi 		    _sip_msg_t **);
11540cb5e5dSvi static int	sip_srv_xaction_inv_res(sip_conn_object_t, sip_xaction_t *,
11640cb5e5dSvi 		    _sip_msg_t *);
11740cb5e5dSvi static int	sip_srv_xaction_noninv_res(sip_conn_object_t, sip_xaction_t *,
11840cb5e5dSvi 		    _sip_msg_t *);
11940cb5e5dSvi static int	sip_create_send_nonOKack(sip_conn_object_t, sip_xaction_t *,
12040cb5e5dSvi 		    _sip_msg_t *, boolean_t);
12140cb5e5dSvi void		sip_xaction_state_timer_fire(void *);
12240cb5e5dSvi 
12340cb5e5dSvi static sip_xaction_time_obj_t	*sip_setup_timer(sip_conn_object_t,
12440cb5e5dSvi 				    sip_xaction_t *, _sip_msg_t *,
12540cb5e5dSvi 				    sip_timer_t, int);
12640cb5e5dSvi 
12740cb5e5dSvi /*
12840cb5e5dSvi  * Return a timer object
12940cb5e5dSvi  */
13040cb5e5dSvi 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)13140cb5e5dSvi sip_setup_timer(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
13240cb5e5dSvi     _sip_msg_t *sip_msg, sip_timer_t timer, int type)
13340cb5e5dSvi {
13440cb5e5dSvi 	sip_xaction_time_obj_t	*sip_timer_obj = NULL;
13540cb5e5dSvi 
13640cb5e5dSvi 	sip_timer_obj = (sip_xaction_time_obj_t *)
13740cb5e5dSvi 	    malloc(sizeof (sip_xaction_time_obj_t));
13840cb5e5dSvi 	if (sip_timer_obj == NULL)
13940cb5e5dSvi 		return (NULL);
14040cb5e5dSvi 	if (SIP_IS_TIMER_RUNNING(timer))
14140cb5e5dSvi 		SIP_CANCEL_TIMER(timer);
14240cb5e5dSvi 	sip_timer_obj->sip_xaction_timer_type = type;
14340cb5e5dSvi 	sip_timer_obj->sip_xaction_timer_xport = sip_conn_transport(conn_obj);
14440cb5e5dSvi 	sip_timer_obj->sip_trans = sip_trans;
14540cb5e5dSvi 	/*
14640cb5e5dSvi 	 * Save the message
14740cb5e5dSvi 	 */
14840cb5e5dSvi 	if (sip_msg != NULL) {
14940cb5e5dSvi 		(void) sip_add_conn_obj_cache(conn_obj, (void *)sip_trans);
15040cb5e5dSvi 		if (sip_trans->sip_xaction_last_msg != NULL) {
15140cb5e5dSvi 			SIP_MSG_REFCNT_DECR(sip_trans->sip_xaction_last_msg);
15240cb5e5dSvi 			sip_trans->sip_xaction_last_msg = NULL;
15340cb5e5dSvi 		}
15440cb5e5dSvi 		SIP_MSG_REFCNT_INCR(sip_msg);
15540cb5e5dSvi 		sip_trans->sip_xaction_last_msg = sip_msg;
15640cb5e5dSvi 	}
15740cb5e5dSvi 	return (sip_timer_obj);
15840cb5e5dSvi }
15940cb5e5dSvi 
16040cb5e5dSvi /*
16140cb5e5dSvi  * --------------------------- Output Routines ---------------------------
16240cb5e5dSvi  */
16340cb5e5dSvi 
16440cb5e5dSvi /*
16540cb5e5dSvi  * Send a SIP message, request or response, out
16640cb5e5dSvi  */
16740cb5e5dSvi int
sip_xaction_output(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t * msg)16840cb5e5dSvi sip_xaction_output(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
16940cb5e5dSvi     _sip_msg_t *msg)
17040cb5e5dSvi {
17140cb5e5dSvi 	sip_message_type_t	*sip_msg_info;
17240cb5e5dSvi 	int			ret;
17340cb5e5dSvi 
174*943efbc3Sgm 	if (conn_obj == NULL) {
175*943efbc3Sgm 		(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
176*943efbc3Sgm 		sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
177*943efbc3Sgm 		    SIP_ASSERT_ERROR, __FILE__, __LINE__);
178*943efbc3Sgm 		(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
179*943efbc3Sgm 	}
18040cb5e5dSvi 	assert(conn_obj != NULL);
18140cb5e5dSvi 	sip_msg_info = msg->sip_msg_req_res;
18240cb5e5dSvi 
183*943efbc3Sgm 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
184*943efbc3Sgm 	sip_trans->sip_xaction_msgcnt++;
185*943efbc3Sgm 	sip_add_log(&sip_trans->sip_xaction_log[sip_trans->sip_xaction_state],
186*943efbc3Sgm 	    (sip_msg_t)msg, sip_trans->sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
187*943efbc3Sgm 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
188*943efbc3Sgm 
18940cb5e5dSvi 	if (sip_msg_info->is_request)
19040cb5e5dSvi 		return (sip_clnt_xaction_output(conn_obj, sip_trans, msg));
19140cb5e5dSvi 
19240cb5e5dSvi 	ret = sip_srv_xaction_output(conn_obj, sip_trans, msg);
19340cb5e5dSvi 
19440cb5e5dSvi 	return (ret);
19540cb5e5dSvi }
19640cb5e5dSvi 
19740cb5e5dSvi /*
19840cb5e5dSvi  * Send a Request out
19940cb5e5dSvi  */
20040cb5e5dSvi static int
sip_clnt_xaction_output(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t * msg)20140cb5e5dSvi sip_clnt_xaction_output(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
20240cb5e5dSvi     _sip_msg_t *msg)
20340cb5e5dSvi {
20440cb5e5dSvi 	sip_xaction_time_obj_t	*timer_obj_A = NULL;
20540cb5e5dSvi 	sip_xaction_time_obj_t	*timer_obj_B = NULL;
20640cb5e5dSvi 	sip_xaction_time_obj_t	*timer_obj_E = NULL;
20740cb5e5dSvi 	sip_xaction_time_obj_t	*timer_obj_F = NULL;
20840cb5e5dSvi 	sip_message_type_t	*sip_msg_info;
20940cb5e5dSvi 	int			prev_state;
21040cb5e5dSvi 	int			error = 0;
21140cb5e5dSvi 	boolean_t		isreliable;
21240cb5e5dSvi 
21340cb5e5dSvi 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
21440cb5e5dSvi 	prev_state = sip_trans->sip_xaction_state;
215*943efbc3Sgm 	if (msg->sip_msg_req_res == NULL) {
216*943efbc3Sgm 		sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
217*943efbc3Sgm 		    SIP_ASSERT_ERROR, __FILE__, __LINE__);
218*943efbc3Sgm 	}
21940cb5e5dSvi 	assert(msg->sip_msg_req_res != NULL);
22040cb5e5dSvi 	sip_msg_info = msg->sip_msg_req_res;
22140cb5e5dSvi 	isreliable = sip_is_conn_reliable(conn_obj);
22240cb5e5dSvi 
22340cb5e5dSvi 	if (sip_msg_info->sip_req_method == INVITE) {
22440cb5e5dSvi 		/*
22540cb5e5dSvi 		 * if transport is not reliable, start TIMER A.
22640cb5e5dSvi 		 */
22740cb5e5dSvi 		if (!isreliable) {
22840cb5e5dSvi 			timer_obj_A = sip_setup_timer(conn_obj, sip_trans,
22940cb5e5dSvi 			    msg, sip_trans->sip_xaction_TA,
23040cb5e5dSvi 			    SIP_XACTION_TIMER_A);
23140cb5e5dSvi 			if (timer_obj_A == NULL) {
23240cb5e5dSvi 				error = ENOMEM;
23340cb5e5dSvi 				goto error_ret;
23440cb5e5dSvi 			}
23540cb5e5dSvi 		}
23640cb5e5dSvi 
23740cb5e5dSvi 		timer_obj_B = sip_setup_timer(conn_obj, sip_trans, NULL,
23840cb5e5dSvi 		    sip_trans->sip_xaction_TB, SIP_XACTION_TIMER_B);
23940cb5e5dSvi 		if (timer_obj_B == NULL) {
24040cb5e5dSvi 			error = ENOMEM;
24140cb5e5dSvi 			goto error_ret;
24240cb5e5dSvi 		}
24340cb5e5dSvi 		if (timer_obj_A != NULL) {
24440cb5e5dSvi 			SIP_SCHED_TIMER(sip_trans->sip_xaction_TA, timer_obj_A,
24540cb5e5dSvi 			    sip_xaction_state_timer_fire);
24640cb5e5dSvi 			if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TA)) {
24740cb5e5dSvi 				error = ENOMEM;
24840cb5e5dSvi 				goto error_ret;
24940cb5e5dSvi 			}
25040cb5e5dSvi 		}
25140cb5e5dSvi 		SIP_SCHED_TIMER(sip_trans->sip_xaction_TB, timer_obj_B,
25240cb5e5dSvi 		    sip_xaction_state_timer_fire);
25340cb5e5dSvi 		if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TB)) {
25440cb5e5dSvi 			if (timer_obj_A != NULL)
25540cb5e5dSvi 				SIP_CANCEL_TIMER(sip_trans->sip_xaction_TA)
25640cb5e5dSvi 			error = ENOMEM;
25740cb5e5dSvi 			goto error_ret;
25840cb5e5dSvi 		}
25940cb5e5dSvi 		sip_trans->sip_xaction_state = SIP_CLNT_CALLING;
26040cb5e5dSvi 	} else {
26140cb5e5dSvi 		/*
26240cb5e5dSvi 		 * if transport is not reliable, start rexmit Timer E.
26340cb5e5dSvi 		 */
26440cb5e5dSvi 		if (!isreliable) {
26540cb5e5dSvi 			timer_obj_E = sip_setup_timer(conn_obj, sip_trans, msg,
26640cb5e5dSvi 			    sip_trans->sip_xaction_TE, SIP_XACTION_TIMER_E);
26740cb5e5dSvi 			if (timer_obj_E == NULL) {
26840cb5e5dSvi 				error = ENOMEM;
26940cb5e5dSvi 				goto error_ret;
27040cb5e5dSvi 			}
27140cb5e5dSvi 		}
27240cb5e5dSvi 		/*
27340cb5e5dSvi 		 * Start transaction Timer F
27440cb5e5dSvi 		 */
27540cb5e5dSvi 		timer_obj_F = sip_setup_timer(conn_obj, sip_trans, NULL,
27640cb5e5dSvi 		    sip_trans->sip_xaction_TF, SIP_XACTION_TIMER_F);
27740cb5e5dSvi 		if (timer_obj_F == NULL) {
27840cb5e5dSvi 			error = ENOMEM;
27940cb5e5dSvi 			goto error_ret;
28040cb5e5dSvi 		}
28140cb5e5dSvi 		if (timer_obj_E != NULL) {
28240cb5e5dSvi 			SIP_SCHED_TIMER(sip_trans->sip_xaction_TE, timer_obj_E,
28340cb5e5dSvi 			    sip_xaction_state_timer_fire);
28440cb5e5dSvi 			if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TE)) {
28540cb5e5dSvi 				error = ENOMEM;
28640cb5e5dSvi 				goto error_ret;
28740cb5e5dSvi 			}
28840cb5e5dSvi 		}
28940cb5e5dSvi 		SIP_SCHED_TIMER(sip_trans->sip_xaction_TF, timer_obj_F,
29040cb5e5dSvi 		    sip_xaction_state_timer_fire);
29140cb5e5dSvi 		if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TF)) {
29240cb5e5dSvi 			if (timer_obj_E != NULL)
29340cb5e5dSvi 				SIP_CANCEL_TIMER(sip_trans->sip_xaction_TE)
29440cb5e5dSvi 			error = ENOMEM;
29540cb5e5dSvi 			goto error_ret;
29640cb5e5dSvi 		}
29740cb5e5dSvi 		sip_trans->sip_xaction_state = SIP_CLNT_TRYING;
29840cb5e5dSvi 	}
29940cb5e5dSvi 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
30040cb5e5dSvi 	if (sip_xaction_ulp_state_cb != NULL) {
30140cb5e5dSvi 		sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
30240cb5e5dSvi 		    (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
30340cb5e5dSvi 	}
30440cb5e5dSvi 	return (0);
30540cb5e5dSvi 
30640cb5e5dSvi error_ret:
30740cb5e5dSvi 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
30840cb5e5dSvi 	if (timer_obj_A != NULL)
30940cb5e5dSvi 		free(timer_obj_A);
31040cb5e5dSvi 	if (timer_obj_B != NULL)
31140cb5e5dSvi 		free(timer_obj_B);
31240cb5e5dSvi 	if (timer_obj_E != NULL)
31340cb5e5dSvi 		free(timer_obj_E);
31440cb5e5dSvi 	if (timer_obj_F != NULL)
31540cb5e5dSvi 		free(timer_obj_F);
31640cb5e5dSvi 	return (error);
31740cb5e5dSvi }
31840cb5e5dSvi 
31940cb5e5dSvi /*
32040cb5e5dSvi  * Send a response out
32140cb5e5dSvi  */
32240cb5e5dSvi static int
sip_srv_xaction_output(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t * msg)32340cb5e5dSvi sip_srv_xaction_output(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
32440cb5e5dSvi     _sip_msg_t *msg)
32540cb5e5dSvi {
32640cb5e5dSvi 	int		ret;
32740cb5e5dSvi 
32840cb5e5dSvi 	if (sip_trans->sip_xaction_method == INVITE)
32940cb5e5dSvi 		ret = sip_srv_xaction_inv_res(conn_obj, sip_trans, msg);
33040cb5e5dSvi 	else
33140cb5e5dSvi 		ret = sip_srv_xaction_noninv_res(conn_obj, sip_trans, msg);
33240cb5e5dSvi 	return (ret);
33340cb5e5dSvi }
33440cb5e5dSvi 
33540cb5e5dSvi /*
33640cb5e5dSvi  * Send a INVITE response out
33740cb5e5dSvi  */
33840cb5e5dSvi static int
sip_srv_xaction_inv_res(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t * msg)33940cb5e5dSvi sip_srv_xaction_inv_res(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
34040cb5e5dSvi     _sip_msg_t *msg)
34140cb5e5dSvi {
34240cb5e5dSvi 	int			resp_code;
34340cb5e5dSvi 	sip_xaction_time_obj_t	*timer_obj_G = NULL;
34440cb5e5dSvi 	sip_xaction_time_obj_t	*timer_obj_H = NULL;
34540cb5e5dSvi 	sip_message_type_t	*sip_msg_info = msg->sip_msg_req_res;
34640cb5e5dSvi 	int			prev_state;
34740cb5e5dSvi 	boolean_t		isreliable;
34840cb5e5dSvi 
34940cb5e5dSvi 	isreliable = sip_is_conn_reliable(conn_obj);
35040cb5e5dSvi 
35140cb5e5dSvi 	resp_code = sip_msg_info->sip_resp_code;
35240cb5e5dSvi 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
35340cb5e5dSvi 	prev_state = sip_trans->sip_xaction_state;
35440cb5e5dSvi 	switch (sip_trans->sip_xaction_state) {
35540cb5e5dSvi 		case SIP_SRV_INV_PROCEEDING:
35640cb5e5dSvi 			if (SIP_PROVISIONAL_RESP(resp_code)) {
35740cb5e5dSvi 				if (sip_trans->sip_xaction_last_msg != NULL) {
35840cb5e5dSvi 					SIP_MSG_REFCNT_DECR(
35940cb5e5dSvi 					    sip_trans->sip_xaction_last_msg);
36040cb5e5dSvi 					sip_trans->sip_xaction_last_msg = NULL;
36140cb5e5dSvi 				}
36240cb5e5dSvi 				SIP_MSG_REFCNT_INCR(msg);
36340cb5e5dSvi 				sip_trans->sip_xaction_last_msg = msg;
36440cb5e5dSvi 				(void) sip_add_conn_obj_cache(conn_obj,
36540cb5e5dSvi 				    (void *)sip_trans);
36640cb5e5dSvi 			} else if (SIP_OK_RESP(resp_code)) {
36740cb5e5dSvi 				sip_trans->sip_xaction_state =
36840cb5e5dSvi 				    SIP_SRV_INV_TERMINATED;
36940cb5e5dSvi 			} else  if (SIP_NONOK_FINAL_RESP(resp_code)) {
37040cb5e5dSvi 				if (sip_trans->sip_xaction_last_msg != NULL) {
37140cb5e5dSvi 					SIP_MSG_REFCNT_DECR(
37240cb5e5dSvi 					    sip_trans->sip_xaction_last_msg);
37340cb5e5dSvi 					sip_trans->sip_xaction_last_msg = NULL;
37440cb5e5dSvi 				}
37540cb5e5dSvi 				SIP_MSG_REFCNT_INCR(msg);
37640cb5e5dSvi 				sip_trans->sip_xaction_last_msg = msg;
37740cb5e5dSvi 				(void) sip_add_conn_obj_cache(conn_obj,
37840cb5e5dSvi 				    (void *)sip_trans);
37940cb5e5dSvi 				/*
38040cb5e5dSvi 				 * For unreliable transport start timer G
38140cb5e5dSvi 				 */
38240cb5e5dSvi 				if (!isreliable) {
38340cb5e5dSvi 					timer_obj_G = sip_setup_timer(
38440cb5e5dSvi 					    conn_obj, sip_trans,
38540cb5e5dSvi 					    NULL, sip_trans->sip_xaction_TG,
38640cb5e5dSvi 					    SIP_XACTION_TIMER_G);
38740cb5e5dSvi 					if (timer_obj_G == NULL) {
38840cb5e5dSvi 						(void) pthread_mutex_unlock(
38940cb5e5dSvi 						    &sip_trans->
39040cb5e5dSvi 						    sip_xaction_mutex);
39140cb5e5dSvi 						return (ENOMEM);
39240cb5e5dSvi 					}
39340cb5e5dSvi 				}
39440cb5e5dSvi 				/*
39540cb5e5dSvi 				 * Start Timer H
39640cb5e5dSvi 				 */
39740cb5e5dSvi 				timer_obj_H = sip_setup_timer(
39840cb5e5dSvi 				    conn_obj, sip_trans,
39940cb5e5dSvi 				    NULL, sip_trans->sip_xaction_TH,
40040cb5e5dSvi 				    SIP_XACTION_TIMER_H);
40140cb5e5dSvi 				if (timer_obj_H == NULL) {
40240cb5e5dSvi 					if (timer_obj_G != NULL)
40340cb5e5dSvi 						free(timer_obj_G);
40440cb5e5dSvi 					(void) pthread_mutex_unlock(
40540cb5e5dSvi 					    &sip_trans->sip_xaction_mutex);
40640cb5e5dSvi 					return (ENOMEM);
40740cb5e5dSvi 				}
40840cb5e5dSvi 				if (timer_obj_G != NULL) {
40940cb5e5dSvi 					SIP_SCHED_TIMER(
41040cb5e5dSvi 					    sip_trans->sip_xaction_TG,
41140cb5e5dSvi 					    timer_obj_G,
41240cb5e5dSvi 					    sip_xaction_state_timer_fire);
41340cb5e5dSvi 					if (!SIP_IS_TIMER_RUNNING(
41440cb5e5dSvi 					    sip_trans->sip_xaction_TG)) {
41540cb5e5dSvi 						(void) pthread_mutex_unlock(
41640cb5e5dSvi 						    &sip_trans->
41740cb5e5dSvi 						    sip_xaction_mutex);
41840cb5e5dSvi 						free(timer_obj_G);
41940cb5e5dSvi 						return (ENOMEM);
42040cb5e5dSvi 					}
42140cb5e5dSvi 				}
42240cb5e5dSvi 				if (timer_obj_H != NULL) {
42340cb5e5dSvi 					SIP_SCHED_TIMER(
42440cb5e5dSvi 					    sip_trans->sip_xaction_TH,
42540cb5e5dSvi 					    timer_obj_H,
42640cb5e5dSvi 					    sip_xaction_state_timer_fire);
42740cb5e5dSvi 					if (!SIP_IS_TIMER_RUNNING(
42840cb5e5dSvi 					    sip_trans->sip_xaction_TH)) {
42940cb5e5dSvi 						if (timer_obj_G != NULL) {
43040cb5e5dSvi 							SIP_CANCEL_TIMER(
43140cb5e5dSvi 							    sip_trans->
43240cb5e5dSvi 							    sip_xaction_TG);
43340cb5e5dSvi 							free(timer_obj_G);
43440cb5e5dSvi 						}
43540cb5e5dSvi 						(void) pthread_mutex_unlock(
43640cb5e5dSvi 						    &sip_trans->
43740cb5e5dSvi 						    sip_xaction_mutex);
43840cb5e5dSvi 						free(timer_obj_H);
43940cb5e5dSvi 						return (ENOMEM);
44040cb5e5dSvi 					}
44140cb5e5dSvi 				}
44240cb5e5dSvi 				sip_trans->sip_xaction_state =
44340cb5e5dSvi 				    SIP_SRV_INV_COMPLETED;
44440cb5e5dSvi 			}
44540cb5e5dSvi 			break;
44640cb5e5dSvi 		default:
44740cb5e5dSvi 			(void) pthread_mutex_unlock(
44840cb5e5dSvi 			    &sip_trans->sip_xaction_mutex);
44940cb5e5dSvi 			return (EPROTO);
45040cb5e5dSvi 	}
45140cb5e5dSvi 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
45240cb5e5dSvi 	if (prev_state != sip_trans->sip_xaction_state &&
45340cb5e5dSvi 	    sip_xaction_ulp_state_cb != NULL) {
45440cb5e5dSvi 		sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
45540cb5e5dSvi 		    (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
45640cb5e5dSvi 	}
45740cb5e5dSvi 	return (0);
45840cb5e5dSvi }
45940cb5e5dSvi 
46040cb5e5dSvi /*
46140cb5e5dSvi  *  Send a NON-INVITE response out
46240cb5e5dSvi  */
46340cb5e5dSvi static int
sip_srv_xaction_noninv_res(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t * msg)46440cb5e5dSvi sip_srv_xaction_noninv_res(sip_conn_object_t conn_obj,
46540cb5e5dSvi     sip_xaction_t *sip_trans, _sip_msg_t *msg)
46640cb5e5dSvi {
46740cb5e5dSvi 	int			resp_code;
46840cb5e5dSvi 	sip_xaction_time_obj_t	*timer_obj_J = NULL;
46940cb5e5dSvi 	sip_message_type_t	*sip_msg_info = msg->sip_msg_req_res;
47040cb5e5dSvi 	int			prev_state;
47140cb5e5dSvi 	boolean_t		isreliable;
47240cb5e5dSvi 
47340cb5e5dSvi 	resp_code = sip_msg_info->sip_resp_code;
47440cb5e5dSvi 	isreliable = sip_is_conn_reliable(conn_obj);
47540cb5e5dSvi 
47640cb5e5dSvi 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
47740cb5e5dSvi 	prev_state = sip_trans->sip_xaction_state;
47840cb5e5dSvi 	switch (sip_trans->sip_xaction_state) {
47940cb5e5dSvi 		case SIP_SRV_TRYING:
48040cb5e5dSvi 			if (sip_trans->sip_xaction_last_msg != NULL) {
48140cb5e5dSvi 				SIP_MSG_REFCNT_DECR(
48240cb5e5dSvi 				    sip_trans->sip_xaction_last_msg);
48340cb5e5dSvi 				sip_trans->sip_xaction_last_msg = NULL;
48440cb5e5dSvi 			}
48540cb5e5dSvi 			SIP_MSG_REFCNT_INCR(msg);
48640cb5e5dSvi 			sip_trans->sip_xaction_last_msg = msg;
48740cb5e5dSvi 			(void) sip_add_conn_obj_cache(conn_obj,
48840cb5e5dSvi 			    (void *)sip_trans);
48940cb5e5dSvi 			if (SIP_PROVISIONAL_RESP(resp_code)) {
49040cb5e5dSvi 				sip_trans->sip_xaction_state =
49140cb5e5dSvi 				    SIP_SRV_NONINV_PROCEEDING;
49240cb5e5dSvi 			} else if (SIP_FINAL_RESP(resp_code)) {
49340cb5e5dSvi 				/*
49440cb5e5dSvi 				 * For unreliable transports, start Timer J
49540cb5e5dSvi 				 */
49640cb5e5dSvi 				if (!isreliable) {
49740cb5e5dSvi 					timer_obj_J = sip_setup_timer(
49840cb5e5dSvi 					    conn_obj, sip_trans,
49940cb5e5dSvi 					    NULL, sip_trans->sip_xaction_TJ,
50040cb5e5dSvi 					    SIP_XACTION_TIMER_J);
50140cb5e5dSvi 					if (timer_obj_J == NULL) {
50240cb5e5dSvi 						(void) pthread_mutex_unlock(&
50340cb5e5dSvi 						    sip_trans->
50440cb5e5dSvi 						    sip_xaction_mutex);
50540cb5e5dSvi 						return (ENOMEM);
50640cb5e5dSvi 					}
50740cb5e5dSvi 					SIP_SCHED_TIMER(
50840cb5e5dSvi 					    sip_trans->sip_xaction_TJ,
50940cb5e5dSvi 					    timer_obj_J,
51040cb5e5dSvi 					    sip_xaction_state_timer_fire);
51140cb5e5dSvi 					if (!SIP_IS_TIMER_RUNNING(
51240cb5e5dSvi 					    sip_trans->sip_xaction_TJ)) {
51340cb5e5dSvi 						(void) pthread_mutex_unlock(&
51440cb5e5dSvi 						    sip_trans->
51540cb5e5dSvi 						    sip_xaction_mutex);
51640cb5e5dSvi 						free(timer_obj_J);
51740cb5e5dSvi 						return (ENOMEM);
51840cb5e5dSvi 					}
51940cb5e5dSvi 					sip_trans->sip_xaction_state =
52040cb5e5dSvi 					    SIP_SRV_NONINV_COMPLETED;
52140cb5e5dSvi 				} else {
52240cb5e5dSvi 					sip_trans->sip_xaction_state =
52340cb5e5dSvi 					    SIP_SRV_NONINV_TERMINATED;
52440cb5e5dSvi 				}
52540cb5e5dSvi 			}
52640cb5e5dSvi 			break;
52740cb5e5dSvi 		case SIP_SRV_NONINV_PROCEEDING:
52840cb5e5dSvi 			if (sip_trans->sip_xaction_last_msg != NULL) {
52940cb5e5dSvi 				SIP_MSG_REFCNT_DECR(
53040cb5e5dSvi 				    sip_trans->sip_xaction_last_msg);
53140cb5e5dSvi 				sip_trans->sip_xaction_last_msg = NULL;
53240cb5e5dSvi 			}
53340cb5e5dSvi 			SIP_MSG_REFCNT_INCR(msg);
53440cb5e5dSvi 			sip_trans->sip_xaction_last_msg = msg;
53540cb5e5dSvi 			(void) sip_add_conn_obj_cache(conn_obj,
53640cb5e5dSvi 			    (void *)sip_trans);
53740cb5e5dSvi 			if (SIP_PROVISIONAL_RESP(resp_code)) {
53840cb5e5dSvi 				break;
53940cb5e5dSvi 			} else if (SIP_FINAL_RESP(resp_code)) {
54040cb5e5dSvi 				/*
54140cb5e5dSvi 				 * For unreliable transports, start Timer J
54240cb5e5dSvi 				 */
54340cb5e5dSvi 				if (!isreliable) {
54440cb5e5dSvi 					timer_obj_J = sip_setup_timer(
54540cb5e5dSvi 					    conn_obj, sip_trans,
54640cb5e5dSvi 					    NULL, sip_trans->sip_xaction_TJ,
54740cb5e5dSvi 					    SIP_XACTION_TIMER_J);
54840cb5e5dSvi 					if (timer_obj_J == NULL) {
54940cb5e5dSvi 						(void) pthread_mutex_unlock(&
55040cb5e5dSvi 						    sip_trans->
55140cb5e5dSvi 						    sip_xaction_mutex);
55240cb5e5dSvi 						return (ENOMEM);
55340cb5e5dSvi 					}
55440cb5e5dSvi 					SIP_SCHED_TIMER(
55540cb5e5dSvi 					    sip_trans->sip_xaction_TJ,
55640cb5e5dSvi 					    timer_obj_J,
55740cb5e5dSvi 					    sip_xaction_state_timer_fire);
55840cb5e5dSvi 					if (!SIP_IS_TIMER_RUNNING(
55940cb5e5dSvi 					    sip_trans->sip_xaction_TJ)) {
56040cb5e5dSvi 						(void) pthread_mutex_unlock(&
56140cb5e5dSvi 						    sip_trans->
56240cb5e5dSvi 						    sip_xaction_mutex);
56340cb5e5dSvi 						free(timer_obj_J);
56440cb5e5dSvi 						return (ENOMEM);
56540cb5e5dSvi 					}
56640cb5e5dSvi 					sip_trans->sip_xaction_state =
56740cb5e5dSvi 					    SIP_SRV_NONINV_COMPLETED;
56840cb5e5dSvi 				} else {
56940cb5e5dSvi 					sip_trans->sip_xaction_state =
57040cb5e5dSvi 					    SIP_SRV_NONINV_TERMINATED;
57140cb5e5dSvi 				}
57240cb5e5dSvi 			}
57340cb5e5dSvi 			break;
57440cb5e5dSvi 		default:
57540cb5e5dSvi 			(void) pthread_mutex_unlock(
57640cb5e5dSvi 			    &sip_trans->sip_xaction_mutex);
57740cb5e5dSvi 			return (EPROTO);
57840cb5e5dSvi 	}
57940cb5e5dSvi 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
58040cb5e5dSvi 	if (prev_state != sip_trans->sip_xaction_state &&
58140cb5e5dSvi 	    sip_xaction_ulp_state_cb != NULL) {
58240cb5e5dSvi 		sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
58340cb5e5dSvi 		    (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
58440cb5e5dSvi 	}
58540cb5e5dSvi 	return (0);
58640cb5e5dSvi }
58740cb5e5dSvi 
58840cb5e5dSvi 
58940cb5e5dSvi /*
59040cb5e5dSvi  * -------------------------- Input Routines ---------------------------
59140cb5e5dSvi  */
59240cb5e5dSvi 
59340cb5e5dSvi /*
59440cb5e5dSvi  * Process an incoming SIP message Request or Response
59540cb5e5dSvi  */
59640cb5e5dSvi int
sip_xaction_input(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t ** sip_msg)59740cb5e5dSvi sip_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
59840cb5e5dSvi     _sip_msg_t **sip_msg)
59940cb5e5dSvi {
60040cb5e5dSvi 	sip_message_type_t	*sip_msg_info;
60140cb5e5dSvi 	int			ret;
60240cb5e5dSvi 
60340cb5e5dSvi 	sip_msg_info = (*sip_msg)->sip_msg_req_res;
604*943efbc3Sgm 
605*943efbc3Sgm 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
606*943efbc3Sgm 	sip_trans->sip_xaction_msgcnt++;
607*943efbc3Sgm 	sip_add_log(&sip_trans->sip_xaction_log[sip_trans->sip_xaction_state],
608*943efbc3Sgm 	    (sip_msg_t)*sip_msg, sip_trans->sip_xaction_msgcnt,
609*943efbc3Sgm 	    SIP_TRANSACTION_LOG);
610*943efbc3Sgm 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
611*943efbc3Sgm 
61240cb5e5dSvi 	if (sip_msg_info->is_request)
61340cb5e5dSvi 		ret = sip_srv_xaction_input(conn_obj, sip_trans, sip_msg);
61440cb5e5dSvi 	else
61540cb5e5dSvi 		ret = sip_clnt_xaction_input(conn_obj, sip_trans, sip_msg);
61640cb5e5dSvi 	return (ret);
61740cb5e5dSvi }
61840cb5e5dSvi 
61940cb5e5dSvi /*
62040cb5e5dSvi  * Process a Request from the transport
62140cb5e5dSvi  */
62240cb5e5dSvi static int
sip_srv_xaction_input(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t ** sip_msg)62340cb5e5dSvi sip_srv_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
62440cb5e5dSvi     _sip_msg_t **sip_msg)
62540cb5e5dSvi {
62640cb5e5dSvi 	sip_message_type_t	*sip_msg_info;
62740cb5e5dSvi 	_sip_msg_t		*msg = *sip_msg;
62840cb5e5dSvi 	int			prev_state;
62940cb5e5dSvi 	boolean_t		isreliable;
63040cb5e5dSvi 
63140cb5e5dSvi 	sip_msg_info = msg->sip_msg_req_res;
63240cb5e5dSvi 	isreliable = sip_is_conn_reliable(conn_obj);
63340cb5e5dSvi 
63440cb5e5dSvi 	/*
63540cb5e5dSvi 	 * Cancel if the original transaction has not yet got a final
63640cb5e5dSvi 	 * response and send a 487 response.
63740cb5e5dSvi 	 */
63840cb5e5dSvi 	if (sip_msg_info->sip_req_method == ACK) {
63940cb5e5dSvi 		_sip_msg_t		*sip_last_resp;
64040cb5e5dSvi 		const sip_str_t		*resp_to_tag;
64140cb5e5dSvi 		const sip_str_t		*req_to_tag;
64240cb5e5dSvi 		int			error;
64340cb5e5dSvi 		sip_message_type_t	*last_msg_info;
64440cb5e5dSvi 
64540cb5e5dSvi 		(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
64640cb5e5dSvi 
64740cb5e5dSvi 		if (sip_trans->sip_xaction_last_msg != NULL)
64840cb5e5dSvi 			sip_last_resp = sip_trans->sip_xaction_last_msg;
64940cb5e5dSvi 		else
65040cb5e5dSvi 			sip_last_resp = sip_trans->sip_xaction_orig_msg;
65140cb5e5dSvi 		last_msg_info = sip_last_resp->sip_msg_req_res;
65240cb5e5dSvi 		if (last_msg_info->is_request) {
65340cb5e5dSvi 			(void) pthread_mutex_unlock(
65440cb5e5dSvi 			    &sip_trans->sip_xaction_mutex);
65540cb5e5dSvi 			return (0);
65640cb5e5dSvi 		}
65740cb5e5dSvi 		req_to_tag = sip_get_to_tag((sip_msg_t)msg, &error);
65840cb5e5dSvi 		if (req_to_tag == NULL || error != 0) {
65940cb5e5dSvi 			(void) pthread_mutex_unlock(
66040cb5e5dSvi 			    &sip_trans->sip_xaction_mutex);
66140cb5e5dSvi 			return (0);
66240cb5e5dSvi 		}
66340cb5e5dSvi 		resp_to_tag = sip_get_to_tag((sip_msg_t)sip_last_resp,
66440cb5e5dSvi 		    &error);
66540cb5e5dSvi 		if (req_to_tag == NULL || error != 0) {
66640cb5e5dSvi 			(void) pthread_mutex_unlock(
66740cb5e5dSvi 			    &sip_trans->sip_xaction_mutex);
66840cb5e5dSvi 			return (0);
66940cb5e5dSvi 		}
67040cb5e5dSvi 		if (resp_to_tag->sip_str_len != req_to_tag->sip_str_len ||
67140cb5e5dSvi 		    strncmp(resp_to_tag->sip_str_ptr, req_to_tag->sip_str_ptr,
672*943efbc3Sgm 		    req_to_tag->sip_str_len) != 0) {
67340cb5e5dSvi 			(void) pthread_mutex_unlock(
67440cb5e5dSvi 			    &sip_trans->sip_xaction_mutex);
67540cb5e5dSvi 			return (0);
67640cb5e5dSvi 		}
67740cb5e5dSvi 		prev_state = sip_trans->sip_xaction_state;
67840cb5e5dSvi 		if (sip_trans->sip_xaction_state == SIP_SRV_INV_COMPLETED) {
67940cb5e5dSvi 			sip_xaction_time_obj_t	*timer_obj_I = NULL;
68040cb5e5dSvi 
68140cb5e5dSvi 			SIP_CANCEL_TIMER(sip_trans->sip_xaction_TG);
68240cb5e5dSvi 			/*
68340cb5e5dSvi 			 * Cancel Timer H and goto TERMINATED state for
68440cb5e5dSvi 			 * reliable transports.
68540cb5e5dSvi 			 */
68640cb5e5dSvi 			if (isreliable) {
68740cb5e5dSvi 				SIP_CANCEL_TIMER(
68840cb5e5dSvi 				    sip_trans->sip_xaction_TH);
68940cb5e5dSvi 				sip_trans->sip_xaction_state =
69040cb5e5dSvi 				    SIP_SRV_INV_TERMINATED;
69140cb5e5dSvi 				(void) pthread_mutex_unlock(
69240cb5e5dSvi 				    &sip_trans->sip_xaction_mutex);
69340cb5e5dSvi 				if (sip_xaction_ulp_state_cb != NULL) {
69440cb5e5dSvi 					sip_xaction_ulp_state_cb(
69540cb5e5dSvi 					    (sip_transaction_t)sip_trans,
69640cb5e5dSvi 					    (sip_msg_t)msg, prev_state,
69740cb5e5dSvi 					    sip_trans->sip_xaction_state);
69840cb5e5dSvi 				}
69940cb5e5dSvi 				return (0);
70040cb5e5dSvi 			}
70140cb5e5dSvi 			/*
70240cb5e5dSvi 			 * For unreliable transports, start TIMER I and
70340cb5e5dSvi 			 * transition to CONFIRMED state.
70440cb5e5dSvi 			 */
70540cb5e5dSvi 			timer_obj_I = sip_setup_timer(conn_obj, sip_trans,
70640cb5e5dSvi 			    NULL,
70740cb5e5dSvi 			    sip_trans->sip_xaction_TI, SIP_XACTION_TIMER_I);
70840cb5e5dSvi 			if (timer_obj_I == NULL) {
70940cb5e5dSvi 				(void) pthread_mutex_unlock(
71040cb5e5dSvi 				    &sip_trans->sip_xaction_mutex);
71140cb5e5dSvi 				return (ENOMEM);
71240cb5e5dSvi 			}
71340cb5e5dSvi 			SIP_SCHED_TIMER(sip_trans->sip_xaction_TI,
71440cb5e5dSvi 			    timer_obj_I, sip_xaction_state_timer_fire);
71540cb5e5dSvi 			if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TI)) {
71640cb5e5dSvi 				(void) pthread_mutex_unlock(
71740cb5e5dSvi 				    &sip_trans->sip_xaction_mutex);
71840cb5e5dSvi 				free(timer_obj_I);
71940cb5e5dSvi 				return (ENOMEM);
72040cb5e5dSvi 			}
72140cb5e5dSvi 			sip_trans->sip_xaction_state = SIP_SRV_CONFIRMED;
72240cb5e5dSvi 		}
72340cb5e5dSvi 		(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
72440cb5e5dSvi 		if (prev_state != sip_trans->sip_xaction_state &&
72540cb5e5dSvi 		    sip_xaction_ulp_state_cb != NULL) {
72640cb5e5dSvi 			sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
72740cb5e5dSvi 			    (sip_msg_t)msg, prev_state,
72840cb5e5dSvi 			    sip_trans->sip_xaction_state);
72940cb5e5dSvi 		}
73040cb5e5dSvi 		return (0);
73140cb5e5dSvi 	} else if (sip_msg_info->sip_req_method == CANCEL) {
73240cb5e5dSvi 		if (sip_trans->sip_xaction_method == INVITE) {
73340cb5e5dSvi 			(void) pthread_mutex_unlock(
73440cb5e5dSvi 			    &sip_trans->sip_xaction_mutex);
73540cb5e5dSvi 			return (0);
73640cb5e5dSvi 		}
73740cb5e5dSvi 	}
73840cb5e5dSvi 	if (sip_msg_info->sip_req_method == INVITE) {
73940cb5e5dSvi 		(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
740*943efbc3Sgm 		if (sip_trans->sip_xaction_method != INVITE) {
741*943efbc3Sgm 			sip_write_to_log((void *)sip_trans,
742*943efbc3Sgm 			    SIP_TRANSACTION_LOG | SIP_ASSERT_ERROR, __FILE__,
743*943efbc3Sgm 			    __LINE__);
744*943efbc3Sgm 		}
74540cb5e5dSvi 		assert(sip_trans->sip_xaction_method == INVITE);
74640cb5e5dSvi 		/*
74740cb5e5dSvi 		 * Retransmitted invite
74840cb5e5dSvi 		 */
74940cb5e5dSvi 		switch (sip_trans->sip_xaction_state) {
75040cb5e5dSvi 			case SIP_SRV_INV_PROCEEDING:
75140cb5e5dSvi 			case SIP_SRV_INV_COMPLETED:
75240cb5e5dSvi 				if (sip_trans->sip_xaction_last_msg != NULL) {
753*943efbc3Sgm 					_sip_msg_t		*new_msg;
754*943efbc3Sgm 					sip_message_type_t	*msg_info;
755*943efbc3Sgm 					int			resp;
75640cb5e5dSvi 
75740cb5e5dSvi 					new_msg =
75840cb5e5dSvi 					    sip_trans->sip_xaction_last_msg;
759*943efbc3Sgm 					msg_info = new_msg->sip_msg_req_res;
760*943efbc3Sgm 					if (msg_info == NULL || msg_info->
761*943efbc3Sgm 					    is_request) {
762*943efbc3Sgm 						sip_write_to_log((void *)
763*943efbc3Sgm 						    sip_trans,
764*943efbc3Sgm 						    SIP_TRANSACTION_LOG |
765*943efbc3Sgm 						    SIP_ASSERT_ERROR, __FILE__,
766*943efbc3Sgm 						    __LINE__);
767*943efbc3Sgm 					}
768*943efbc3Sgm 					assert(msg_info != NULL && !msg_info->
769*943efbc3Sgm 					    is_request);
770*943efbc3Sgm 					resp = msg_info->sip_resp_code;
771*943efbc3Sgm 					SIP_UPDATE_COUNTERS(B_FALSE, 0, resp,
772*943efbc3Sgm 					    B_TRUE, new_msg->sip_msg_len);
773*943efbc3Sgm 					++sip_trans->sip_xaction_msgcnt;
774*943efbc3Sgm 					sip_add_log(&sip_trans->sip_xaction_log[
775*943efbc3Sgm 					    sip_trans->sip_xaction_state],
776*943efbc3Sgm 					    new_msg, sip_trans->
777*943efbc3Sgm 					    sip_xaction_msgcnt,
778*943efbc3Sgm 					    SIP_TRANSACTION_LOG);
77940cb5e5dSvi 					(void) sip_stack_send(conn_obj,
78040cb5e5dSvi 					    new_msg->sip_msg_buf,
78140cb5e5dSvi 					    new_msg->sip_msg_len);
78240cb5e5dSvi 				}
78340cb5e5dSvi 				break;
78440cb5e5dSvi 			default:
78540cb5e5dSvi 				(void) pthread_mutex_unlock(
78640cb5e5dSvi 				    &sip_trans->sip_xaction_mutex);
78740cb5e5dSvi 				return (EPROTO);
78840cb5e5dSvi 		}
78940cb5e5dSvi 		(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
790*943efbc3Sgm 		/*
791*943efbc3Sgm 		 * We need to account for this invite received by the stack
792*943efbc3Sgm 		 * before we free that message.
793*943efbc3Sgm 		 */
794*943efbc3Sgm 		SIP_UPDATE_COUNTERS(B_TRUE, INVITE, 0, B_FALSE,
795*943efbc3Sgm 		    msg->sip_msg_len);
79640cb5e5dSvi 		sip_free_msg((sip_msg_t)msg);
79740cb5e5dSvi 		*sip_msg = NULL;
79840cb5e5dSvi 		return (0);
79940cb5e5dSvi 	}
80040cb5e5dSvi 	/*
80140cb5e5dSvi 	 * Retransmitted request
80240cb5e5dSvi 	 */
80340cb5e5dSvi 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
804*943efbc3Sgm 	if (sip_trans->sip_xaction_method == INVITE) {
805*943efbc3Sgm 		sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
806*943efbc3Sgm 		    SIP_ASSERT_ERROR, __FILE__, __LINE__);
807*943efbc3Sgm 	}
808*943efbc3Sgm 	assert(sip_trans->sip_xaction_method != INVITE);
80940cb5e5dSvi 	switch (sip_trans->sip_xaction_state) {
81040cb5e5dSvi 		case SIP_SRV_NONINV_PROCEEDING:
81140cb5e5dSvi 		case SIP_SRV_NONINV_COMPLETED:
81240cb5e5dSvi 			if (sip_trans->sip_xaction_last_msg != NULL) {
813*943efbc3Sgm 				_sip_msg_t		*new_msg;
814*943efbc3Sgm 				sip_message_type_t	*msg_info;
815*943efbc3Sgm 				int			resp;
81640cb5e5dSvi 
81740cb5e5dSvi 				new_msg = sip_trans->sip_xaction_last_msg;
818*943efbc3Sgm 				msg_info = new_msg->sip_msg_req_res;
819*943efbc3Sgm 				if (msg_info == NULL || msg_info->is_request) {
820*943efbc3Sgm 					sip_write_to_log((void *)sip_trans,
821*943efbc3Sgm 					    SIP_TRANSACTION_LOG |
822*943efbc3Sgm 					    SIP_ASSERT_ERROR, __FILE__,
823*943efbc3Sgm 					    __LINE__);
824*943efbc3Sgm 					}
825*943efbc3Sgm 				assert(msg_info != NULL && !msg_info->
826*943efbc3Sgm 				    is_request);
827*943efbc3Sgm 				resp = msg_info->sip_resp_code;
828*943efbc3Sgm 				SIP_UPDATE_COUNTERS(B_FALSE, 0, resp, B_TRUE,
829*943efbc3Sgm 				    new_msg->sip_msg_len);
830*943efbc3Sgm 				++sip_trans->sip_xaction_msgcnt;
831*943efbc3Sgm 				sip_add_log(&sip_trans->sip_xaction_log[
832*943efbc3Sgm 				    sip_trans->sip_xaction_state], new_msg,
833*943efbc3Sgm 				    sip_trans->sip_xaction_msgcnt,
834*943efbc3Sgm 				    SIP_TRANSACTION_LOG);
83540cb5e5dSvi 				(void) sip_stack_send(conn_obj,
83640cb5e5dSvi 				    new_msg->sip_msg_buf, new_msg->sip_msg_len);
83740cb5e5dSvi 			}
83840cb5e5dSvi 			break;
83940cb5e5dSvi 		default:
84040cb5e5dSvi 			(void) pthread_mutex_unlock(
84140cb5e5dSvi 			    &sip_trans->sip_xaction_mutex);
84240cb5e5dSvi 			return (EPROTO);
84340cb5e5dSvi 	}
84440cb5e5dSvi 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
845*943efbc3Sgm 	/*
846*943efbc3Sgm 	 * We need to account for the retransmitted non-INVITE request here.
847*943efbc3Sgm 	 * When we return from here the msg will be freed and we will not
848*943efbc3Sgm 	 * be able to capture the details at sip_process_new_packet()
849*943efbc3Sgm 	 */
850*943efbc3Sgm 	SIP_UPDATE_COUNTERS(B_TRUE, sip_msg_info->sip_req_method, 0, B_FALSE,
851*943efbc3Sgm 	    msg->sip_msg_len);
85240cb5e5dSvi 	sip_free_msg((sip_msg_t)msg);
85340cb5e5dSvi 	*sip_msg = NULL;
85440cb5e5dSvi 	return (0);
85540cb5e5dSvi }
85640cb5e5dSvi 
85740cb5e5dSvi /*
85840cb5e5dSvi  * Process a Response
85940cb5e5dSvi  */
86040cb5e5dSvi static int
sip_clnt_xaction_input(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t ** msg)86140cb5e5dSvi sip_clnt_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
86240cb5e5dSvi     _sip_msg_t **msg)
86340cb5e5dSvi {
86440cb5e5dSvi 	int		ret;
86540cb5e5dSvi 
86640cb5e5dSvi 	if (sip_trans->sip_xaction_method == INVITE)
86740cb5e5dSvi 		ret = sip_clnt_xaction_inv_res(conn_obj, sip_trans, msg);
86840cb5e5dSvi 	else
86940cb5e5dSvi 		ret = sip_clnt_xaction_noninv_res(conn_obj, sip_trans, msg);
87040cb5e5dSvi 
87140cb5e5dSvi 	return (ret);
87240cb5e5dSvi }
87340cb5e5dSvi 
87440cb5e5dSvi static int
sip_create_send_nonOKack(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t * msg,boolean_t copy)87540cb5e5dSvi sip_create_send_nonOKack(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
87640cb5e5dSvi     _sip_msg_t *msg, boolean_t copy)
87740cb5e5dSvi {
87840cb5e5dSvi 	_sip_msg_t	*ack_msg;
87940cb5e5dSvi 	int		ret = 0;
88040cb5e5dSvi 
88140cb5e5dSvi 	ack_msg = (_sip_msg_t *)sip_new_msg();
88240cb5e5dSvi 	if (ack_msg == NULL)
88340cb5e5dSvi 		return (ENOMEM);
88440cb5e5dSvi 	if ((ret = sip_create_nonOKack(
88540cb5e5dSvi 	    (sip_msg_t)sip_trans->sip_xaction_orig_msg, (sip_msg_t)msg,
88640cb5e5dSvi 	    (sip_msg_t)ack_msg)) != 0) {
88740cb5e5dSvi 		sip_free_msg((sip_msg_t)ack_msg);
88840cb5e5dSvi 		return (ret);
88940cb5e5dSvi 	}
890*943efbc3Sgm 	SIP_UPDATE_COUNTERS(B_TRUE, ACK, 0, B_TRUE, ack_msg->sip_msg_len);
891*943efbc3Sgm 	++sip_trans->sip_xaction_msgcnt;
892*943efbc3Sgm 	sip_add_log(&sip_trans->sip_xaction_log[sip_trans->sip_xaction_state],
893*943efbc3Sgm 	    ack_msg, sip_trans->sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
89440cb5e5dSvi 	if ((ret = sip_stack_send(conn_obj, ack_msg->sip_msg_buf,
89540cb5e5dSvi 	    ack_msg->sip_msg_len)) != 0) {
89640cb5e5dSvi 		sip_free_msg((sip_msg_t)ack_msg);
89740cb5e5dSvi 		return (ret);
89840cb5e5dSvi 	}
89940cb5e5dSvi 	if (copy) {
90040cb5e5dSvi 		SIP_MSG_REFCNT_INCR(ack_msg);
90140cb5e5dSvi 		if (sip_trans->sip_xaction_last_msg != NULL) {
90240cb5e5dSvi 			SIP_MSG_REFCNT_DECR(sip_trans->sip_xaction_last_msg);
90340cb5e5dSvi 			sip_trans->sip_xaction_last_msg = NULL;
90440cb5e5dSvi 		}
90540cb5e5dSvi 		sip_trans->sip_xaction_last_msg = ack_msg;
90640cb5e5dSvi 	}
90740cb5e5dSvi 	sip_free_msg((sip_msg_t)ack_msg);
90840cb5e5dSvi 	return (0);
90940cb5e5dSvi }
91040cb5e5dSvi 
91140cb5e5dSvi /*
91240cb5e5dSvi  * Process a INVITE Response
91340cb5e5dSvi  */
91440cb5e5dSvi static int
sip_clnt_xaction_inv_res(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t ** sip_msg)91540cb5e5dSvi sip_clnt_xaction_inv_res(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
91640cb5e5dSvi     _sip_msg_t **sip_msg)
91740cb5e5dSvi {
91840cb5e5dSvi 	int			resp_code;
91940cb5e5dSvi 	_sip_msg_t		*msg = *sip_msg;
92040cb5e5dSvi 	sip_xaction_time_obj_t	*timer_obj_D = NULL;
92140cb5e5dSvi 	sip_message_type_t	*sip_msg_info;
92240cb5e5dSvi 	int			prev_state;
92340cb5e5dSvi 	boolean_t		isreliable;
92440cb5e5dSvi 
925*943efbc3Sgm 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
926*943efbc3Sgm 	if (msg->sip_msg_req_res == NULL) {
927*943efbc3Sgm 		sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
928*943efbc3Sgm 		    SIP_ASSERT_ERROR, __FILE__, __LINE__);
929*943efbc3Sgm 	}
93040cb5e5dSvi 	assert(msg->sip_msg_req_res != NULL);
93140cb5e5dSvi 
93240cb5e5dSvi 	sip_msg_info = msg->sip_msg_req_res;
93340cb5e5dSvi 	resp_code = sip_msg_info->sip_resp_code;
93440cb5e5dSvi 	isreliable = sip_is_conn_reliable(conn_obj);
93540cb5e5dSvi 
93640cb5e5dSvi 	prev_state = sip_trans->sip_xaction_state;
93740cb5e5dSvi 	switch (sip_trans->sip_xaction_state) {
93840cb5e5dSvi 		case SIP_CLNT_CALLING:
93940cb5e5dSvi 			if (SIP_PROVISIONAL_RESP(resp_code)) {
94040cb5e5dSvi 				/*
94140cb5e5dSvi 				 * sip_trans->sip_xaction_last_msg ?
94240cb5e5dSvi 				 */
94340cb5e5dSvi 				SIP_CANCEL_TIMER(
94440cb5e5dSvi 				    sip_trans->sip_xaction_TA);
94540cb5e5dSvi 				sip_trans->sip_xaction_state =
94640cb5e5dSvi 				    SIP_CLNT_INV_PROCEEDING;
94740cb5e5dSvi 			} else if (SIP_OK_RESP(resp_code)) {
94840cb5e5dSvi 				/*
94940cb5e5dSvi 				 * sip_trans->sip_xaction_last_msg ?
95040cb5e5dSvi 				 */
95140cb5e5dSvi 				SIP_CANCEL_TIMER(
95240cb5e5dSvi 				    sip_trans->sip_xaction_TA);
95340cb5e5dSvi 				SIP_CANCEL_TIMER(
95440cb5e5dSvi 				    sip_trans->sip_xaction_TB);
95540cb5e5dSvi 				sip_trans->sip_xaction_state =
95640cb5e5dSvi 				    SIP_CLNT_INV_TERMINATED;
95740cb5e5dSvi 			} else if (SIP_NONOK_FINAL_RESP(resp_code)) {
95840cb5e5dSvi 				int	ret;
95940cb5e5dSvi 
96040cb5e5dSvi 				/*
96140cb5e5dSvi 				 * sip_trans->sip_xaction_last_msg ?
96240cb5e5dSvi 				 */
96340cb5e5dSvi 				SIP_CANCEL_TIMER(
96440cb5e5dSvi 				    sip_trans->sip_xaction_TA);
96540cb5e5dSvi 				SIP_CANCEL_TIMER(
96640cb5e5dSvi 				    sip_trans->sip_xaction_TB);
96740cb5e5dSvi 				if ((ret = sip_create_send_nonOKack(conn_obj,
96840cb5e5dSvi 				    sip_trans, msg, B_FALSE)) != 0) {
96940cb5e5dSvi 					(void) pthread_mutex_unlock(
97040cb5e5dSvi 					    &sip_trans->sip_xaction_mutex);
97140cb5e5dSvi 					return (ret);
97240cb5e5dSvi 				}
97340cb5e5dSvi 				/*
97440cb5e5dSvi 				 * start timer D for unreliable transports
97540cb5e5dSvi 				 */
97640cb5e5dSvi 				if (!isreliable) {
97740cb5e5dSvi 					timer_obj_D = sip_setup_timer(
97840cb5e5dSvi 					    conn_obj, sip_trans,
97940cb5e5dSvi 					    NULL, sip_trans->sip_xaction_TD,
98040cb5e5dSvi 					    SIP_XACTION_TIMER_D);
98140cb5e5dSvi 					if (timer_obj_D == NULL) {
98240cb5e5dSvi 						(void) pthread_mutex_unlock(
98340cb5e5dSvi 						    &sip_trans->
98440cb5e5dSvi 						    sip_xaction_mutex);
98540cb5e5dSvi 						return (ENOMEM);
98640cb5e5dSvi 					}
98740cb5e5dSvi 					SIP_SCHED_TIMER(
98840cb5e5dSvi 					    sip_trans->sip_xaction_TD,
98940cb5e5dSvi 					    timer_obj_D,
99040cb5e5dSvi 					    sip_xaction_state_timer_fire);
99140cb5e5dSvi 					if (!SIP_IS_TIMER_RUNNING(
99240cb5e5dSvi 					    sip_trans->sip_xaction_TD)) {
99340cb5e5dSvi 						(void) pthread_mutex_unlock(
99440cb5e5dSvi 						    &sip_trans->
99540cb5e5dSvi 						    sip_xaction_mutex);
99640cb5e5dSvi 						free(timer_obj_D);
99740cb5e5dSvi 						return (ENOMEM);
99840cb5e5dSvi 					}
99940cb5e5dSvi 					sip_trans->sip_xaction_state =
100040cb5e5dSvi 					    SIP_CLNT_INV_COMPLETED;
100140cb5e5dSvi 				} else {
100240cb5e5dSvi 					sip_trans->sip_xaction_state =
100340cb5e5dSvi 					    SIP_CLNT_INV_TERMINATED;
100440cb5e5dSvi 				}
100540cb5e5dSvi 			} else {
100640cb5e5dSvi 				/*
100740cb5e5dSvi 				 * Invalid resp_code
100840cb5e5dSvi 				 */
100940cb5e5dSvi 				(void) pthread_mutex_unlock(
101040cb5e5dSvi 				    &sip_trans->sip_xaction_mutex);
101140cb5e5dSvi 				return (EPROTO);
101240cb5e5dSvi 			}
101340cb5e5dSvi 			break;
101440cb5e5dSvi 		case SIP_CLNT_INV_PROCEEDING:
101540cb5e5dSvi 			if (SIP_PROVISIONAL_RESP(resp_code)) {
101640cb5e5dSvi 				break;
101740cb5e5dSvi 			} else if (SIP_OK_RESP(resp_code)) {
101840cb5e5dSvi 				SIP_CANCEL_TIMER(
101940cb5e5dSvi 				    sip_trans->sip_xaction_TB);
102040cb5e5dSvi 				sip_trans->sip_xaction_state =
102140cb5e5dSvi 				    SIP_CLNT_INV_TERMINATED;
102240cb5e5dSvi 			} else if (SIP_NONOK_FINAL_RESP(resp_code)) {
102340cb5e5dSvi 				int	ret;
102440cb5e5dSvi 
102540cb5e5dSvi 				SIP_CANCEL_TIMER(
102640cb5e5dSvi 				    sip_trans->sip_xaction_TB);
102740cb5e5dSvi 				if ((ret = sip_create_send_nonOKack(conn_obj,
102840cb5e5dSvi 				    sip_trans, msg, B_FALSE)) != 0) {
102940cb5e5dSvi 					(void) pthread_mutex_unlock(
103040cb5e5dSvi 					    &sip_trans->sip_xaction_mutex);
103140cb5e5dSvi 					return (ret);
103240cb5e5dSvi 				}
103340cb5e5dSvi 				/*
103440cb5e5dSvi 				 * start timer D for unreliable transports
103540cb5e5dSvi 				 */
103640cb5e5dSvi 				if (!isreliable) {
103740cb5e5dSvi 					timer_obj_D = sip_setup_timer(
103840cb5e5dSvi 					    conn_obj, sip_trans,
103940cb5e5dSvi 					    NULL, sip_trans->sip_xaction_TD,
104040cb5e5dSvi 					    SIP_XACTION_TIMER_D);
104140cb5e5dSvi 					if (timer_obj_D == NULL) {
104240cb5e5dSvi 						(void) pthread_mutex_unlock(
104340cb5e5dSvi 						    &sip_trans->
104440cb5e5dSvi 						    sip_xaction_mutex);
104540cb5e5dSvi 						return (ENOMEM);
104640cb5e5dSvi 					}
104740cb5e5dSvi 					SIP_SCHED_TIMER(
104840cb5e5dSvi 					    sip_trans->sip_xaction_TD,
104940cb5e5dSvi 					    timer_obj_D,
105040cb5e5dSvi 					    sip_xaction_state_timer_fire);
105140cb5e5dSvi 					if (!SIP_IS_TIMER_RUNNING(
105240cb5e5dSvi 					    sip_trans->sip_xaction_TD)) {
105340cb5e5dSvi 						(void) pthread_mutex_unlock(
105440cb5e5dSvi 						    &sip_trans->
105540cb5e5dSvi 						    sip_xaction_mutex);
105640cb5e5dSvi 						free(timer_obj_D);
105740cb5e5dSvi 						return (ENOMEM);
105840cb5e5dSvi 					}
105940cb5e5dSvi 					sip_trans->sip_xaction_state =
106040cb5e5dSvi 					    SIP_CLNT_INV_COMPLETED;
106140cb5e5dSvi 				} else {
106240cb5e5dSvi 					sip_trans->sip_xaction_state =
106340cb5e5dSvi 					    SIP_CLNT_INV_TERMINATED;
106440cb5e5dSvi 				}
106540cb5e5dSvi 			} else {
106640cb5e5dSvi 				(void) pthread_mutex_unlock(
106740cb5e5dSvi 				    &sip_trans->sip_xaction_mutex);
106840cb5e5dSvi 				return (EPROTO);
106940cb5e5dSvi 			}
107040cb5e5dSvi 			break;
107140cb5e5dSvi 		case SIP_CLNT_INV_COMPLETED:
107240cb5e5dSvi 			/*
107340cb5e5dSvi 			 * Transport error takes it to
107440cb5e5dSvi 			 * SIP_CLNT_INV_TERMINATED
107540cb5e5dSvi 			 */
107640cb5e5dSvi 			if (SIP_NONOK_FINAL_RESP(resp_code)) {
107740cb5e5dSvi 				int	ret;
107840cb5e5dSvi 
107940cb5e5dSvi 				if ((ret = sip_create_send_nonOKack(conn_obj,
108040cb5e5dSvi 				    sip_trans, msg, B_FALSE)) != 0) {
108140cb5e5dSvi 					(void) pthread_mutex_unlock(
108240cb5e5dSvi 					    &sip_trans->sip_xaction_mutex);
108340cb5e5dSvi 					return (ret);
108440cb5e5dSvi 				}
108540cb5e5dSvi 			} else {
108640cb5e5dSvi 				/*
108740cb5e5dSvi 				 * Invalid resp_code
108840cb5e5dSvi 				 */
108940cb5e5dSvi 				(void) pthread_mutex_unlock(
109040cb5e5dSvi 				    &sip_trans->sip_xaction_mutex);
109140cb5e5dSvi 				return (EPROTO);
109240cb5e5dSvi 			}
109340cb5e5dSvi 			break;
109440cb5e5dSvi 		default:
109540cb5e5dSvi 			(void) pthread_mutex_unlock(
109640cb5e5dSvi 			    &sip_trans->sip_xaction_mutex);
109740cb5e5dSvi 			return (EPROTO);
109840cb5e5dSvi 	}
109940cb5e5dSvi 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
110040cb5e5dSvi 	if (prev_state != sip_trans->sip_xaction_state &&
110140cb5e5dSvi 	    sip_xaction_ulp_state_cb != NULL) {
110240cb5e5dSvi 		sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
110340cb5e5dSvi 		    (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
110440cb5e5dSvi 	}
110540cb5e5dSvi 	return (0);
110640cb5e5dSvi }
110740cb5e5dSvi 
110840cb5e5dSvi /*
110940cb5e5dSvi  * Process a NON-INVITE Response
111040cb5e5dSvi  */
111140cb5e5dSvi static int
sip_clnt_xaction_noninv_res(sip_conn_object_t conn_obj,sip_xaction_t * sip_trans,_sip_msg_t ** sip_msg)111240cb5e5dSvi sip_clnt_xaction_noninv_res(sip_conn_object_t conn_obj,
111340cb5e5dSvi     sip_xaction_t *sip_trans, _sip_msg_t **sip_msg)
111440cb5e5dSvi {
111540cb5e5dSvi 	int			resp_code;
111640cb5e5dSvi 	sip_xaction_time_obj_t	*timer_obj_K = NULL;
111740cb5e5dSvi 	sip_message_type_t	*sip_msg_info;
111840cb5e5dSvi 	int			prev_state;
111940cb5e5dSvi 	_sip_msg_t		*msg = *sip_msg;
112040cb5e5dSvi 	boolean_t		isreliable;
112140cb5e5dSvi 
1122*943efbc3Sgm 	if (msg->sip_msg_req_res == NULL || sip_trans == NULL) {
1123*943efbc3Sgm 		sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
1124*943efbc3Sgm 		    SIP_ASSERT_ERROR, __FILE__, __LINE__);
1125*943efbc3Sgm 	}
112640cb5e5dSvi 	assert(msg->sip_msg_req_res != NULL);
112740cb5e5dSvi 	assert(sip_trans != NULL);
112840cb5e5dSvi 
112940cb5e5dSvi 	sip_msg_info = msg->sip_msg_req_res;
113040cb5e5dSvi 	isreliable = sip_is_conn_reliable(conn_obj);
113140cb5e5dSvi 	resp_code = sip_msg_info->sip_resp_code;
113240cb5e5dSvi 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
113340cb5e5dSvi 	prev_state = sip_trans->sip_xaction_state;
113440cb5e5dSvi 	switch (sip_trans->sip_xaction_state) {
113540cb5e5dSvi 		case SIP_CLNT_TRYING:
113640cb5e5dSvi 			if (SIP_PROVISIONAL_RESP(resp_code)) {
113740cb5e5dSvi 				sip_trans->sip_xaction_state =
113840cb5e5dSvi 				    SIP_CLNT_NONINV_PROCEEDING;
113940cb5e5dSvi 			} else if (SIP_FINAL_RESP(resp_code)) {
114040cb5e5dSvi 				SIP_CANCEL_TIMER(
114140cb5e5dSvi 				    sip_trans->sip_xaction_TE);
114240cb5e5dSvi 				SIP_CANCEL_TIMER(
114340cb5e5dSvi 				    sip_trans->sip_xaction_TF);
114440cb5e5dSvi 				/*
114540cb5e5dSvi 				 * Start timer K for unreliable transports
114640cb5e5dSvi 				 */
114740cb5e5dSvi 				if (!isreliable) {
114840cb5e5dSvi 					timer_obj_K = sip_setup_timer(
114940cb5e5dSvi 					    conn_obj, sip_trans,
115040cb5e5dSvi 					    NULL, sip_trans->sip_xaction_TK,
115140cb5e5dSvi 					    SIP_XACTION_TIMER_K);
115240cb5e5dSvi 					if (timer_obj_K == NULL) {
115340cb5e5dSvi 						(void) pthread_mutex_unlock(&
115440cb5e5dSvi 						    sip_trans->
115540cb5e5dSvi 						    sip_xaction_mutex);
115640cb5e5dSvi 						return (ENOMEM);
115740cb5e5dSvi 					}
115840cb5e5dSvi 					SIP_SCHED_TIMER(
115940cb5e5dSvi 					    sip_trans->sip_xaction_TK,
116040cb5e5dSvi 					    timer_obj_K,
116140cb5e5dSvi 					    sip_xaction_state_timer_fire);
116240cb5e5dSvi 					if (!SIP_IS_TIMER_RUNNING(
116340cb5e5dSvi 					    sip_trans->sip_xaction_TK)) {
116440cb5e5dSvi 						(void) pthread_mutex_unlock(
116540cb5e5dSvi 						    &sip_trans->
116640cb5e5dSvi 						    sip_xaction_mutex);
116740cb5e5dSvi 						free(timer_obj_K);
116840cb5e5dSvi 						return (ENOMEM);
116940cb5e5dSvi 					}
117040cb5e5dSvi 					sip_trans->sip_xaction_state =
117140cb5e5dSvi 					    SIP_CLNT_NONINV_COMPLETED;
117240cb5e5dSvi 				} else {
117340cb5e5dSvi 					sip_trans->sip_xaction_state =
117440cb5e5dSvi 					    SIP_CLNT_NONINV_TERMINATED;
117540cb5e5dSvi 				}
117640cb5e5dSvi 			}
117740cb5e5dSvi 			break;
117840cb5e5dSvi 		case SIP_CLNT_NONINV_PROCEEDING:
117940cb5e5dSvi 			if (SIP_PROVISIONAL_RESP(resp_code)) {
118040cb5e5dSvi 				break;
118140cb5e5dSvi 			} else if (SIP_FINAL_RESP(resp_code)) {
118240cb5e5dSvi 				SIP_CANCEL_TIMER(
118340cb5e5dSvi 				    sip_trans->sip_xaction_TE);
118440cb5e5dSvi 				SIP_CANCEL_TIMER(
118540cb5e5dSvi 				    sip_trans->sip_xaction_TF);
118640cb5e5dSvi 				/*
118740cb5e5dSvi 				 * Start timer K for unreliable transports
118840cb5e5dSvi 				 */
118940cb5e5dSvi 				if (!isreliable) {
119040cb5e5dSvi 					timer_obj_K = sip_setup_timer(
119140cb5e5dSvi 					    conn_obj, sip_trans,
119240cb5e5dSvi 					    NULL, sip_trans->sip_xaction_TK,
119340cb5e5dSvi 					    SIP_XACTION_TIMER_K);
119440cb5e5dSvi 					if (timer_obj_K == NULL) {
119540cb5e5dSvi 						(void) pthread_mutex_unlock(&
119640cb5e5dSvi 						    sip_trans->
119740cb5e5dSvi 						    sip_xaction_mutex);
119840cb5e5dSvi 						return (ENOMEM);
119940cb5e5dSvi 					}
120040cb5e5dSvi 					SIP_SCHED_TIMER(
120140cb5e5dSvi 					    sip_trans->sip_xaction_TK,
120240cb5e5dSvi 					    timer_obj_K,
120340cb5e5dSvi 					    sip_xaction_state_timer_fire);
120440cb5e5dSvi 					if (!SIP_IS_TIMER_RUNNING(
120540cb5e5dSvi 					    sip_trans->sip_xaction_TK)) {
120640cb5e5dSvi 						(void) pthread_mutex_unlock(
120740cb5e5dSvi 						    &sip_trans->
120840cb5e5dSvi 						    sip_xaction_mutex);
120940cb5e5dSvi 						free(timer_obj_K);
121040cb5e5dSvi 						return (ENOMEM);
121140cb5e5dSvi 					}
121240cb5e5dSvi 					sip_trans->sip_xaction_state =
121340cb5e5dSvi 					    SIP_CLNT_NONINV_COMPLETED;
121440cb5e5dSvi 				} else {
121540cb5e5dSvi 					sip_trans->sip_xaction_state =
121640cb5e5dSvi 					    SIP_CLNT_NONINV_TERMINATED;
121740cb5e5dSvi 				}
121840cb5e5dSvi 			}
121940cb5e5dSvi 			break;
122040cb5e5dSvi 		default:
122140cb5e5dSvi 			(void) pthread_mutex_unlock(
122240cb5e5dSvi 			    &sip_trans->sip_xaction_mutex);
122340cb5e5dSvi 			return (EPROTO);
122440cb5e5dSvi 	}
122540cb5e5dSvi 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
122640cb5e5dSvi 	if (prev_state != sip_trans->sip_xaction_state &&
122740cb5e5dSvi 	    sip_xaction_ulp_state_cb != NULL) {
122840cb5e5dSvi 		sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
122940cb5e5dSvi 		    (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
123040cb5e5dSvi 	}
123140cb5e5dSvi 	return (0);
123240cb5e5dSvi }
123340cb5e5dSvi 
123440cb5e5dSvi /*
123540cb5e5dSvi  * If there is a transport error, sending the message out, terminate the
123640cb5e5dSvi  * transaction.
123740cb5e5dSvi  */
123840cb5e5dSvi /* ARGSUSED */
123940cb5e5dSvi void
sip_xaction_terminate(sip_xaction_t * sip_trans,_sip_msg_t * msg,int transport)124040cb5e5dSvi sip_xaction_terminate(sip_xaction_t *sip_trans, _sip_msg_t *msg, int transport)
124140cb5e5dSvi {
124240cb5e5dSvi 	sip_message_type_t	*sip_msg_info;
124340cb5e5dSvi 	int			state;
124440cb5e5dSvi 	int			prev_state;
124540cb5e5dSvi 
124640cb5e5dSvi 	sip_msg_info = msg->sip_msg_req_res;
124740cb5e5dSvi 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
124840cb5e5dSvi 	if (sip_msg_info->is_request) {
124940cb5e5dSvi 		if (sip_trans->sip_xaction_method == INVITE)
125040cb5e5dSvi 			state = SIP_CLNT_INV_TERMINATED;
125140cb5e5dSvi 		else
125240cb5e5dSvi 			state = SIP_CLNT_NONINV_TERMINATED;
125340cb5e5dSvi 	} else {
125440cb5e5dSvi 		if (sip_trans->sip_xaction_method == INVITE)
125540cb5e5dSvi 			state = SIP_SRV_INV_TERMINATED;
125640cb5e5dSvi 		else
125740cb5e5dSvi 			state = SIP_SRV_NONINV_TERMINATED;
125840cb5e5dSvi 	}
125940cb5e5dSvi 	prev_state = sip_trans->sip_xaction_state;
126040cb5e5dSvi 	sip_trans->sip_xaction_state = state;
126140cb5e5dSvi 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
126240cb5e5dSvi 	if (sip_xaction_ulp_state_cb != NULL) {
126340cb5e5dSvi 		sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
126440cb5e5dSvi 		    (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
126540cb5e5dSvi 	}
126640cb5e5dSvi 	sip_xaction_delete(sip_trans);
126740cb5e5dSvi }
126840cb5e5dSvi 
126940cb5e5dSvi /*
127040cb5e5dSvi  * --------------------------- Timer Routine ---------------------------
127140cb5e5dSvi  */
127240cb5e5dSvi 
127340cb5e5dSvi void
sip_xaction_state_timer_fire(void * args)127440cb5e5dSvi sip_xaction_state_timer_fire(void *args)
127540cb5e5dSvi {
127640cb5e5dSvi 	sip_xaction_time_obj_t	*time_obj = (sip_xaction_time_obj_t *)args;
127740cb5e5dSvi 	sip_xaction_t		*sip_trans = time_obj->sip_trans;
127840cb5e5dSvi 	_sip_msg_t		*new_msg;
127940cb5e5dSvi 	boolean_t		destroy_trans = B_FALSE;
128040cb5e5dSvi 	sip_conn_object_t	conn_obj;
128140cb5e5dSvi 	int			prev_state;
1282*943efbc3Sgm 	sip_message_type_t	*msg_info;
1283*943efbc3Sgm 	int			resp;
1284*943efbc3Sgm 	sip_method_t		method;
128540cb5e5dSvi 
128640cb5e5dSvi 	assert(time_obj != NULL);
128740cb5e5dSvi 
128840cb5e5dSvi 	(void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
128940cb5e5dSvi 	prev_state = sip_trans->sip_xaction_state;
129040cb5e5dSvi 	switch (time_obj->sip_xaction_timer_type) {
129140cb5e5dSvi 		case SIP_XACTION_TIMER_A:
129240cb5e5dSvi 			if (sip_trans->sip_xaction_state != SIP_CLNT_CALLING)
129340cb5e5dSvi 				break;
129440cb5e5dSvi 			/*
129540cb5e5dSvi 			 * Assert candidate
129640cb5e5dSvi 			 */
129740cb5e5dSvi 			if (sip_trans->sip_xaction_last_msg == NULL)
129840cb5e5dSvi 				break;
129940cb5e5dSvi 			if (sip_trans->sip_xaction_conn_obj == NULL)
130040cb5e5dSvi 				break;
130140cb5e5dSvi 			new_msg = sip_trans->sip_xaction_last_msg;
130240cb5e5dSvi 			conn_obj = sip_trans->sip_xaction_conn_obj;
1303*943efbc3Sgm 			/* timer A is for INVITE-RETRANSMIT only */
1304*943efbc3Sgm 			SIP_UPDATE_COUNTERS(B_TRUE, INVITE, 0, B_TRUE, new_msg->
1305*943efbc3Sgm 			    sip_msg_len);
1306*943efbc3Sgm 			++sip_trans->sip_xaction_msgcnt;
1307*943efbc3Sgm 			sip_add_log(&sip_trans->sip_xaction_log[sip_trans->
1308*943efbc3Sgm 			    sip_xaction_state], new_msg, sip_trans->
1309*943efbc3Sgm 			    sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
131040cb5e5dSvi 			if (sip_stack_send(conn_obj, new_msg->sip_msg_buf,
131140cb5e5dSvi 			    new_msg->sip_msg_len) != 0) {
131240cb5e5dSvi 				sip_del_conn_obj_cache(
131340cb5e5dSvi 				    sip_trans->sip_xaction_conn_obj,
131440cb5e5dSvi 				    (void *)sip_trans);
131540cb5e5dSvi 				sip_trans->sip_xaction_state =
131640cb5e5dSvi 				    SIP_CLNT_INV_TERMINATED;
131740cb5e5dSvi 				(void) pthread_mutex_unlock(
131840cb5e5dSvi 				    &sip_trans->sip_xaction_mutex);
131940cb5e5dSvi 				if (sip_xaction_ulp_state_cb != NULL) {
1320*943efbc3Sgm 					sip_xaction_ulp_state_cb(
1321*943efbc3Sgm 					    (sip_transaction_t)sip_trans, NULL,
1322*943efbc3Sgm 					    prev_state, sip_trans->
1323*943efbc3Sgm 					    sip_xaction_state);
132440cb5e5dSvi 				}
132540cb5e5dSvi 				if (sip_xaction_ulp_trans_err != NULL) {
132640cb5e5dSvi 					sip_xaction_ulp_trans_err(sip_trans, 0,
132740cb5e5dSvi 					    NULL);
132840cb5e5dSvi 				}
132940cb5e5dSvi 				sip_xaction_delete(sip_trans);
133040cb5e5dSvi 				free(time_obj);
133140cb5e5dSvi 				return;
133240cb5e5dSvi 			}
133340cb5e5dSvi 			SIP_SET_TIMEOUT(sip_trans->sip_xaction_TA,
133440cb5e5dSvi 			    2 * SIP_GET_TIMEOUT(sip_trans->sip_xaction_TA));
133540cb5e5dSvi 			/*
133640cb5e5dSvi 			 * Reschedule the timer
133740cb5e5dSvi 			 */
133840cb5e5dSvi 			SIP_SCHED_TIMER(sip_trans->sip_xaction_TA,
133940cb5e5dSvi 			    time_obj, sip_xaction_state_timer_fire);
134040cb5e5dSvi 			if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TA)) {
134140cb5e5dSvi 				sip_del_conn_obj_cache(
134240cb5e5dSvi 				    sip_trans->sip_xaction_conn_obj,
134340cb5e5dSvi 				    (void *)sip_trans);
134440cb5e5dSvi 				sip_trans->sip_xaction_state =
134540cb5e5dSvi 				    SIP_CLNT_INV_TERMINATED;
134640cb5e5dSvi 				(void) pthread_mutex_unlock(
134740cb5e5dSvi 				    &sip_trans->sip_xaction_mutex);
134840cb5e5dSvi 				if (sip_xaction_ulp_state_cb != NULL) {
1349*943efbc3Sgm 					sip_xaction_ulp_state_cb(
1350*943efbc3Sgm 					    (sip_transaction_t)sip_trans, NULL,
1351*943efbc3Sgm 					    prev_state, sip_trans->
1352*943efbc3Sgm 					    sip_xaction_state);
135340cb5e5dSvi 				}
135440cb5e5dSvi 				if (sip_xaction_ulp_trans_err != NULL) {
135540cb5e5dSvi 					sip_xaction_ulp_trans_err(sip_trans, 0,
135640cb5e5dSvi 					    NULL);
135740cb5e5dSvi 				}
135840cb5e5dSvi 				sip_xaction_delete(sip_trans);
135940cb5e5dSvi 				free(time_obj);
136040cb5e5dSvi 				return;
136140cb5e5dSvi 			}
136240cb5e5dSvi 			(void) pthread_mutex_unlock(
136340cb5e5dSvi 			    &sip_trans->sip_xaction_mutex);
136440cb5e5dSvi 			return;
136540cb5e5dSvi 		case SIP_XACTION_TIMER_B:
136640cb5e5dSvi 			SIP_CANCEL_TIMER(sip_trans->sip_xaction_TA);
136740cb5e5dSvi 			if (sip_trans->sip_xaction_state == SIP_CLNT_CALLING) {
136840cb5e5dSvi 				sip_trans->sip_xaction_state =
136940cb5e5dSvi 				    SIP_CLNT_INV_TERMINATED;
137040cb5e5dSvi 				(void) pthread_mutex_unlock(
137140cb5e5dSvi 				    &sip_trans->sip_xaction_mutex);
137240cb5e5dSvi 				if (sip_xaction_ulp_state_cb != NULL) {
1373*943efbc3Sgm 					sip_xaction_ulp_state_cb(
1374*943efbc3Sgm 					    (sip_transaction_t)sip_trans, NULL,
1375*943efbc3Sgm 					    prev_state, sip_trans->
1376*943efbc3Sgm 					    sip_xaction_state);
137740cb5e5dSvi 				}
137840cb5e5dSvi 				if (sip_xaction_ulp_trans_err != NULL) {
137940cb5e5dSvi 					sip_xaction_ulp_trans_err(sip_trans, 0,
138040cb5e5dSvi 					    NULL);
138140cb5e5dSvi 				}
138240cb5e5dSvi 				sip_xaction_delete(sip_trans);
138340cb5e5dSvi 				free(time_obj);
138440cb5e5dSvi 				return;
138540cb5e5dSvi 			}
138640cb5e5dSvi 			break;
138740cb5e5dSvi 		case SIP_XACTION_TIMER_D:
138840cb5e5dSvi 			if (sip_trans->sip_xaction_state ==
138940cb5e5dSvi 			    SIP_CLNT_INV_COMPLETED) {
139040cb5e5dSvi 				SIP_CANCEL_TIMER(
139140cb5e5dSvi 				    sip_trans->sip_xaction_TB);
139240cb5e5dSvi 				sip_trans->sip_xaction_state =
139340cb5e5dSvi 				    SIP_CLNT_INV_TERMINATED;
139440cb5e5dSvi 				destroy_trans = B_TRUE;
139540cb5e5dSvi 			}
139640cb5e5dSvi 			break;
139740cb5e5dSvi 		case SIP_XACTION_TIMER_E:
139840cb5e5dSvi 			/*
139940cb5e5dSvi 			 * Assert candidate
140040cb5e5dSvi 			 */
140140cb5e5dSvi 			if (sip_trans->sip_xaction_state != SIP_CLNT_TRYING &&
140240cb5e5dSvi 			    sip_trans->sip_xaction_state !=
140340cb5e5dSvi 			    SIP_CLNT_NONINV_PROCEEDING) {
140440cb5e5dSvi 				break;
140540cb5e5dSvi 			}
140640cb5e5dSvi 			/*
140740cb5e5dSvi 			 * Assert candidate
140840cb5e5dSvi 			 */
140940cb5e5dSvi 			if (sip_trans->sip_xaction_last_msg == NULL)
141040cb5e5dSvi 				break;
141140cb5e5dSvi 			if (sip_trans->sip_xaction_conn_obj == NULL)
141240cb5e5dSvi 				break;
141340cb5e5dSvi 			conn_obj = sip_trans->sip_xaction_conn_obj;
141440cb5e5dSvi 			new_msg = sip_trans->sip_xaction_last_msg;
1415*943efbc3Sgm 			/* Timer E is for non-INVITE request */
1416*943efbc3Sgm 
1417*943efbc3Sgm 			msg_info = new_msg->sip_msg_req_res;
1418*943efbc3Sgm 			if (msg_info == NULL || !msg_info->is_request) {
1419*943efbc3Sgm 				(void) sip_write_to_log((void *) sip_trans,
1420*943efbc3Sgm 				    SIP_TRANSACTION_LOG | SIP_ASSERT_ERROR,
1421*943efbc3Sgm 				    __FILE__, __LINE__);
1422*943efbc3Sgm 			}
1423*943efbc3Sgm 			assert(msg_info != NULL && msg_info->is_request);
1424*943efbc3Sgm 			method = msg_info->sip_req_method;
1425*943efbc3Sgm 			SIP_UPDATE_COUNTERS(B_TRUE, method, 0, B_TRUE, new_msg->
1426*943efbc3Sgm 			    sip_msg_len);
1427*943efbc3Sgm 			++sip_trans->sip_xaction_msgcnt;
1428*943efbc3Sgm 			sip_add_log(&sip_trans->sip_xaction_log[sip_trans->
1429*943efbc3Sgm 			    sip_xaction_state], new_msg, sip_trans->
1430*943efbc3Sgm 			    sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
143140cb5e5dSvi 			if (sip_stack_send(conn_obj, new_msg->sip_msg_buf,
143240cb5e5dSvi 			    new_msg->sip_msg_len) != 0) {
143340cb5e5dSvi 				sip_del_conn_obj_cache(
143440cb5e5dSvi 				    sip_trans->sip_xaction_conn_obj,
143540cb5e5dSvi 				    (void *)sip_trans);
143640cb5e5dSvi 				sip_trans->sip_xaction_state =
143740cb5e5dSvi 				    SIP_CLNT_NONINV_TERMINATED;
143840cb5e5dSvi 				(void) pthread_mutex_unlock(
143940cb5e5dSvi 				    &sip_trans->sip_xaction_mutex);
144040cb5e5dSvi 				if (sip_xaction_ulp_state_cb != NULL) {
1441*943efbc3Sgm 					sip_xaction_ulp_state_cb(
1442*943efbc3Sgm 					    (sip_transaction_t)sip_trans, NULL,
1443*943efbc3Sgm 					    prev_state, sip_trans->
1444*943efbc3Sgm 					    sip_xaction_state);
144540cb5e5dSvi 				}
144640cb5e5dSvi 				if (sip_xaction_ulp_trans_err != NULL) {
144740cb5e5dSvi 					sip_xaction_ulp_trans_err(sip_trans, 0,
144840cb5e5dSvi 					    NULL);
144940cb5e5dSvi 				}
145040cb5e5dSvi 				sip_xaction_delete(sip_trans);
145140cb5e5dSvi 				free(time_obj);
145240cb5e5dSvi 				return;
145340cb5e5dSvi 			}
145440cb5e5dSvi 			SIP_SET_TIMEOUT(sip_trans->sip_xaction_TE,
145540cb5e5dSvi 			    MIN(SIP_TIMER_T2,
145640cb5e5dSvi 			    2 * SIP_GET_TIMEOUT(sip_trans->sip_xaction_TE)));
145740cb5e5dSvi 			/*
145840cb5e5dSvi 			 * Reschedule the timer
145940cb5e5dSvi 			 */
146040cb5e5dSvi 			SIP_SCHED_TIMER(sip_trans->sip_xaction_TE,
146140cb5e5dSvi 			    time_obj, sip_xaction_state_timer_fire);
146240cb5e5dSvi 			if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TE)) {
146340cb5e5dSvi 				sip_del_conn_obj_cache(
146440cb5e5dSvi 				    sip_trans->sip_xaction_conn_obj,
146540cb5e5dSvi 				    (void *)sip_trans);
146640cb5e5dSvi 				sip_trans->sip_xaction_state =
146740cb5e5dSvi 				    SIP_CLNT_NONINV_TERMINATED;
146840cb5e5dSvi 				(void) pthread_mutex_unlock(
146940cb5e5dSvi 				    &sip_trans->sip_xaction_mutex);
147040cb5e5dSvi 				if (sip_xaction_ulp_state_cb != NULL) {
1471*943efbc3Sgm 					sip_xaction_ulp_state_cb(
1472*943efbc3Sgm 					    (sip_transaction_t)sip_trans, NULL,
1473*943efbc3Sgm 					    prev_state, sip_trans->
1474*943efbc3Sgm 					    sip_xaction_state);
147540cb5e5dSvi 				}
147640cb5e5dSvi 				if (sip_xaction_ulp_trans_err != NULL) {
147740cb5e5dSvi 					sip_xaction_ulp_trans_err(sip_trans, 0,
147840cb5e5dSvi 					    NULL);
147940cb5e5dSvi 				}
148040cb5e5dSvi 				sip_xaction_delete(sip_trans);
148140cb5e5dSvi 				free(time_obj);
148240cb5e5dSvi 				return;
148340cb5e5dSvi 			}
148440cb5e5dSvi 			(void) pthread_mutex_unlock(
148540cb5e5dSvi 			    &sip_trans->sip_xaction_mutex);
148640cb5e5dSvi 			return;
148740cb5e5dSvi 		case SIP_XACTION_TIMER_F:
148840cb5e5dSvi 			SIP_CANCEL_TIMER(sip_trans->sip_xaction_TE);
148940cb5e5dSvi 			if (sip_trans->sip_xaction_state == SIP_CLNT_TRYING ||
149040cb5e5dSvi 			    sip_trans->sip_xaction_state ==
149140cb5e5dSvi 			    SIP_CLNT_NONINV_PROCEEDING) {
149240cb5e5dSvi 				sip_trans->sip_xaction_state =
149340cb5e5dSvi 				    SIP_CLNT_NONINV_TERMINATED;
149440cb5e5dSvi 				(void) pthread_mutex_unlock(
149540cb5e5dSvi 				    &sip_trans->sip_xaction_mutex);
149640cb5e5dSvi 				if (sip_xaction_ulp_state_cb != NULL) {
1497*943efbc3Sgm 					sip_xaction_ulp_state_cb(
1498*943efbc3Sgm 					    (sip_transaction_t)sip_trans, NULL,
1499*943efbc3Sgm 					    prev_state, sip_trans->
1500*943efbc3Sgm 					    sip_xaction_state);
150140cb5e5dSvi 				}
150240cb5e5dSvi 				if (sip_xaction_ulp_trans_err != NULL) {
150340cb5e5dSvi 					sip_xaction_ulp_trans_err(sip_trans, 0,
150440cb5e5dSvi 					    NULL);
150540cb5e5dSvi 				}
150640cb5e5dSvi 				sip_xaction_delete(sip_trans);
150740cb5e5dSvi 				free(time_obj);
150840cb5e5dSvi 				return;
150940cb5e5dSvi 			}
151040cb5e5dSvi 			break;
151140cb5e5dSvi 		case SIP_XACTION_TIMER_G:
151240cb5e5dSvi 			/*
151340cb5e5dSvi 			 * Assert candidate
151440cb5e5dSvi 			 */
151540cb5e5dSvi 			if (sip_trans->sip_xaction_last_msg == NULL)
151640cb5e5dSvi 				break;
151740cb5e5dSvi 			if (sip_trans->sip_xaction_conn_obj == NULL)
151840cb5e5dSvi 				break;
151940cb5e5dSvi 			if (sip_trans->sip_xaction_state !=
152040cb5e5dSvi 			    SIP_SRV_INV_COMPLETED) {
152140cb5e5dSvi 				break;
152240cb5e5dSvi 			}
152340cb5e5dSvi 			new_msg = sip_trans->sip_xaction_last_msg;
152440cb5e5dSvi 			conn_obj = sip_trans->sip_xaction_conn_obj;
1525*943efbc3Sgm 			msg_info = new_msg->sip_msg_req_res;
1526*943efbc3Sgm 			if (msg_info == NULL || msg_info->is_request) {
1527*943efbc3Sgm 				(void) sip_write_to_log((void *) sip_trans,
1528*943efbc3Sgm 				    SIP_TRANSACTION_LOG | SIP_ASSERT_ERROR,
1529*943efbc3Sgm 				    __FILE__, __LINE__);
1530*943efbc3Sgm 			}
1531*943efbc3Sgm 			assert(msg_info != NULL && !msg_info->is_request);
1532*943efbc3Sgm 			resp = msg_info->sip_resp_code;
1533*943efbc3Sgm 			SIP_UPDATE_COUNTERS(B_FALSE, 0, resp, B_TRUE, new_msg->
1534*943efbc3Sgm 			    sip_msg_len);
1535*943efbc3Sgm 			++sip_trans->sip_xaction_msgcnt;
1536*943efbc3Sgm 			sip_add_log(&sip_trans->sip_xaction_log[sip_trans->
1537*943efbc3Sgm 			    sip_xaction_state], new_msg, sip_trans->
1538*943efbc3Sgm 			    sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
153940cb5e5dSvi 			if (sip_stack_send(conn_obj, new_msg->sip_msg_buf,
154040cb5e5dSvi 			    new_msg->sip_msg_len) != 0) {
154140cb5e5dSvi 				sip_del_conn_obj_cache(
154240cb5e5dSvi 				    sip_trans->sip_xaction_conn_obj,
154340cb5e5dSvi 				    (void *)sip_trans);
154440cb5e5dSvi 				sip_trans->sip_xaction_state =
154540cb5e5dSvi 				    SIP_SRV_INV_TERMINATED;
154640cb5e5dSvi 				(void) pthread_mutex_unlock(
154740cb5e5dSvi 				    &sip_trans->sip_xaction_mutex);
154840cb5e5dSvi 				if (sip_xaction_ulp_state_cb != NULL) {
1549*943efbc3Sgm 					sip_xaction_ulp_state_cb(
1550*943efbc3Sgm 					    (sip_transaction_t)sip_trans, NULL,
1551*943efbc3Sgm 					    prev_state, sip_trans->
1552*943efbc3Sgm 					    sip_xaction_state);
155340cb5e5dSvi 				}
155440cb5e5dSvi 				if (sip_xaction_ulp_trans_err != NULL) {
155540cb5e5dSvi 					sip_xaction_ulp_trans_err(sip_trans, 0,
155640cb5e5dSvi 					    NULL);
155740cb5e5dSvi 				}
155840cb5e5dSvi 				sip_xaction_delete(sip_trans);
155940cb5e5dSvi 				free(time_obj);
156040cb5e5dSvi 				return;
156140cb5e5dSvi 			}
156240cb5e5dSvi 			SIP_SET_TIMEOUT(sip_trans->sip_xaction_TG,
156340cb5e5dSvi 			    MIN(SIP_TIMER_T2,
156440cb5e5dSvi 			    2 * SIP_GET_TIMEOUT(sip_trans->sip_xaction_TG)));
156540cb5e5dSvi 			SIP_SCHED_TIMER(sip_trans->sip_xaction_TG,
156640cb5e5dSvi 			    time_obj, sip_xaction_state_timer_fire);
156740cb5e5dSvi 			if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TG)) {
156840cb5e5dSvi 				sip_del_conn_obj_cache(
156940cb5e5dSvi 				    sip_trans->sip_xaction_conn_obj,
157040cb5e5dSvi 				    (void *)sip_trans);
157140cb5e5dSvi 				sip_trans->sip_xaction_state =
157240cb5e5dSvi 				    SIP_SRV_INV_TERMINATED;
157340cb5e5dSvi 				(void) pthread_mutex_unlock(
157440cb5e5dSvi 				    &sip_trans->sip_xaction_mutex);
157540cb5e5dSvi 				if (sip_xaction_ulp_state_cb != NULL) {
1576*943efbc3Sgm 					sip_xaction_ulp_state_cb(
1577*943efbc3Sgm 					    (sip_transaction_t)sip_trans, NULL,
1578*943efbc3Sgm 					    prev_state, sip_trans->
1579*943efbc3Sgm 					    sip_xaction_state);
158040cb5e5dSvi 				}
158140cb5e5dSvi 				if (sip_xaction_ulp_trans_err != NULL) {
158240cb5e5dSvi 					sip_xaction_ulp_trans_err(sip_trans, 0,
158340cb5e5dSvi 					    NULL);
158440cb5e5dSvi 				}
158540cb5e5dSvi 				sip_xaction_delete(sip_trans);
158640cb5e5dSvi 				free(time_obj);
158740cb5e5dSvi 				return;
158840cb5e5dSvi 			}
158940cb5e5dSvi 			(void) pthread_mutex_unlock(
159040cb5e5dSvi 			    &sip_trans->sip_xaction_mutex);
159140cb5e5dSvi 			return;
159240cb5e5dSvi 		case SIP_XACTION_TIMER_H:
159340cb5e5dSvi 			SIP_CANCEL_TIMER(sip_trans->sip_xaction_TG);
159440cb5e5dSvi 			if (sip_trans->sip_xaction_state ==
159540cb5e5dSvi 			    SIP_SRV_INV_COMPLETED) {
159640cb5e5dSvi 				sip_trans->sip_xaction_state =
159740cb5e5dSvi 				    SIP_SRV_INV_TERMINATED;
159840cb5e5dSvi 				(void) pthread_mutex_unlock(
159940cb5e5dSvi 				    &sip_trans->sip_xaction_mutex);
160040cb5e5dSvi 				if (sip_xaction_ulp_state_cb != NULL) {
1601*943efbc3Sgm 					sip_xaction_ulp_state_cb(
1602*943efbc3Sgm 					    (sip_transaction_t)sip_trans, NULL,
1603*943efbc3Sgm 					    prev_state, sip_trans->
1604*943efbc3Sgm 					    sip_xaction_state);
160540cb5e5dSvi 				}
160640cb5e5dSvi 				if (sip_xaction_ulp_trans_err != NULL) {
160740cb5e5dSvi 					sip_xaction_ulp_trans_err(sip_trans, 0,
160840cb5e5dSvi 					    NULL);
160940cb5e5dSvi 				}
161040cb5e5dSvi 				sip_xaction_delete(sip_trans);
161140cb5e5dSvi 				free(time_obj);
161240cb5e5dSvi 				return;
161340cb5e5dSvi 			}
161440cb5e5dSvi 			break;
161540cb5e5dSvi 		case SIP_XACTION_TIMER_I:
161640cb5e5dSvi 			if (sip_trans->sip_xaction_state ==
161740cb5e5dSvi 			    SIP_SRV_CONFIRMED) {
161840cb5e5dSvi 				SIP_CANCEL_TIMER(
161940cb5e5dSvi 				    sip_trans->sip_xaction_TH);
162040cb5e5dSvi 				sip_trans->sip_xaction_state =
162140cb5e5dSvi 				    SIP_SRV_INV_TERMINATED;
162240cb5e5dSvi 				destroy_trans = B_TRUE;
162340cb5e5dSvi 			}
162440cb5e5dSvi 			break;
162540cb5e5dSvi 		case SIP_XACTION_TIMER_J:
162640cb5e5dSvi 			if (sip_trans->sip_xaction_state ==
162740cb5e5dSvi 			    SIP_SRV_NONINV_COMPLETED) {
162840cb5e5dSvi 				sip_trans->sip_xaction_state =
162940cb5e5dSvi 				    SIP_SRV_NONINV_TERMINATED;
163040cb5e5dSvi 				destroy_trans = B_TRUE;
163140cb5e5dSvi 
163240cb5e5dSvi 			}
163340cb5e5dSvi 			break;
163440cb5e5dSvi 		case SIP_XACTION_TIMER_K:
163540cb5e5dSvi 			if (sip_trans->sip_xaction_state ==
163640cb5e5dSvi 			    SIP_CLNT_NONINV_COMPLETED) {
163740cb5e5dSvi 				SIP_CANCEL_TIMER(
163840cb5e5dSvi 				    sip_trans->sip_xaction_TF);
163940cb5e5dSvi 				sip_trans->sip_xaction_state =
164040cb5e5dSvi 				    SIP_CLNT_NONINV_TERMINATED;
164140cb5e5dSvi 				destroy_trans = B_TRUE;
164240cb5e5dSvi 			}
164340cb5e5dSvi 			break;
164440cb5e5dSvi 		default:
164540cb5e5dSvi 			break;
164640cb5e5dSvi 	}
164740cb5e5dSvi 	if (destroy_trans) {
164840cb5e5dSvi 		(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
164940cb5e5dSvi 		if (sip_xaction_ulp_state_cb != NULL &&
165040cb5e5dSvi 		    prev_state != sip_trans->sip_xaction_state) {
165140cb5e5dSvi 			sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
165240cb5e5dSvi 			    NULL, prev_state, sip_trans->sip_xaction_state);
165340cb5e5dSvi 		}
165440cb5e5dSvi 		sip_xaction_delete(sip_trans);
165540cb5e5dSvi 		free(time_obj);
165640cb5e5dSvi 		return;
165740cb5e5dSvi 	}
165840cb5e5dSvi 	(void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
165940cb5e5dSvi 	if (sip_xaction_ulp_state_cb != NULL &&
166040cb5e5dSvi 	    prev_state != sip_trans->sip_xaction_state) {
166140cb5e5dSvi 		sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans, NULL,
166240cb5e5dSvi 		    prev_state, sip_trans->sip_xaction_state);
166340cb5e5dSvi 	}
166440cb5e5dSvi 	free(time_obj);
166540cb5e5dSvi }
1666