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