8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libsip / common / sip_xaction_state_mc.c
blob409d4ba5ea0623b0b96ca744e69ecf2f69861df4
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * SIP Client/Server Invite/Non-Invite Transaction State machine.
33 #include <stdlib.h>
34 #include <string.h>
35 #include <assert.h>
36 #include <errno.h>
37 #include <pthread.h>
38 #include <sip.h>
40 #include "sip_miscdefs.h"
41 #include "sip_msg.h"
42 #include "sip_xaction.h"
45 * Some Timer related info from RFC 3261, page 265.
47 * ----------------------------------------------------------------------
48 * Timer Value Section Meaning
49 * ----------------------------------------------------------------------
50 * T1 500ms default Section 17.1.1.1 RTT Estimate
51 * T2 4s Section 17.1.2.2 The maximum retransmit
52 * interval for non-INVITE
53 * requests and INVITE
54 * responses
55 * T4 5s Section 17.1.2.2 Maximum duration a
56 * message will
57 * remain in the network
58 * ----------------------------------------------------------------------
59 * Timer A initially T1 Section 17.1.1.2 INVITE request retransmit
60 * interval, for UDP only
61 * Timer B 64*T1 Section 17.1.1.2 INVITE transaction
62 * timeout timer
63 * Timer C > 3min Section 16.6 proxy INVITE transaction
64 * bullet 11 timeout
65 * Timer D > 32s for UDP Section 17.1.1.2 Wait time for response
66 * 0s for TCP/SCTP retransmits
67 * Timer E initially T1 Section 17.1.2.2 non-INVITE request
68 * retransmit interval,
69 * UDP only
70 * Timer F 64*T1 Section 17.1.2.2 non-INVITE transaction
71 * timeout timer
72 * Timer G initially T1 Section 17.2.1 INVITE response
73 * retransmit interval
74 * Timer H 64*T1 Section 17.2.1 Wait time for
75 * ACK receipt
76 * Timer I T4 for UDP Section 17.2.1 Wait time for
77 * 0s for TCP/SCTP ACK retransmits
78 * Timer J 64*T1 for UDP Section 17.2.2 Wait time for
79 * 0s for TCP/SCTP non-INVITE request
80 * retransmits
81 * Timer K T4 for UDP Section 17.1.2.2 Wait time for
82 * 0s for TCP/SCTP response retransmits
83 * ----------------------------------------------------------------------
86 #ifndef MIN
87 #define MIN(a, b) (((a) < (b)) ? (a):(b))
88 #endif
91 * Arg to the timer fire routine
93 typedef struct sip_xaction_timer_obj_s {
94 sip_xaction_timer_type_t sip_xaction_timer_type;
95 sip_xaction_t *sip_trans;
96 int sip_xaction_timer_xport;
97 } sip_xaction_time_obj_t;
99 int sip_xaction_output(sip_conn_object_t, sip_xaction_t *,
100 _sip_msg_t *);
101 int sip_xaction_input(sip_conn_object_t, sip_xaction_t *,
102 _sip_msg_t **);
103 void sip_xaction_terminate(sip_xaction_t *, _sip_msg_t *, int);
105 static int sip_clnt_xaction_output(sip_conn_object_t, sip_xaction_t *,
106 _sip_msg_t *);
107 static int sip_clnt_xaction_input(sip_conn_object_t, sip_xaction_t *,
108 _sip_msg_t **);
109 static int sip_clnt_xaction_inv_res(sip_conn_object_t, sip_xaction_t *,
110 _sip_msg_t **);
111 static int sip_clnt_xaction_noninv_res(sip_conn_object_t, sip_xaction_t *,
112 _sip_msg_t **);
113 static int sip_srv_xaction_output(sip_conn_object_t, sip_xaction_t *,
114 _sip_msg_t *);
115 static int sip_srv_xaction_input(sip_conn_object_t, sip_xaction_t *,
116 _sip_msg_t **);
117 static int sip_srv_xaction_inv_res(sip_conn_object_t, sip_xaction_t *,
118 _sip_msg_t *);
119 static int sip_srv_xaction_noninv_res(sip_conn_object_t, sip_xaction_t *,
120 _sip_msg_t *);
121 static int sip_create_send_nonOKack(sip_conn_object_t, sip_xaction_t *,
122 _sip_msg_t *, boolean_t);
123 void sip_xaction_state_timer_fire(void *);
125 static sip_xaction_time_obj_t *sip_setup_timer(sip_conn_object_t,
126 sip_xaction_t *, _sip_msg_t *,
127 sip_timer_t, int);
130 * Return a timer object
132 static sip_xaction_time_obj_t *
133 sip_setup_timer(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
134 _sip_msg_t *sip_msg, sip_timer_t timer, int type)
136 sip_xaction_time_obj_t *sip_timer_obj = NULL;
138 sip_timer_obj = (sip_xaction_time_obj_t *)
139 malloc(sizeof (sip_xaction_time_obj_t));
140 if (sip_timer_obj == NULL)
141 return (NULL);
142 if (SIP_IS_TIMER_RUNNING(timer))
143 SIP_CANCEL_TIMER(timer);
144 sip_timer_obj->sip_xaction_timer_type = type;
145 sip_timer_obj->sip_xaction_timer_xport = sip_conn_transport(conn_obj);
146 sip_timer_obj->sip_trans = sip_trans;
148 * Save the message
150 if (sip_msg != NULL) {
151 (void) sip_add_conn_obj_cache(conn_obj, (void *)sip_trans);
152 if (sip_trans->sip_xaction_last_msg != NULL) {
153 SIP_MSG_REFCNT_DECR(sip_trans->sip_xaction_last_msg);
154 sip_trans->sip_xaction_last_msg = NULL;
156 SIP_MSG_REFCNT_INCR(sip_msg);
157 sip_trans->sip_xaction_last_msg = sip_msg;
159 return (sip_timer_obj);
163 * --------------------------- Output Routines ---------------------------
167 * Send a SIP message, request or response, out
170 sip_xaction_output(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
171 _sip_msg_t *msg)
173 sip_message_type_t *sip_msg_info;
174 int ret;
176 if (conn_obj == NULL) {
177 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
178 sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
179 SIP_ASSERT_ERROR, __FILE__, __LINE__);
180 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
182 assert(conn_obj != NULL);
183 sip_msg_info = msg->sip_msg_req_res;
185 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
186 sip_trans->sip_xaction_msgcnt++;
187 sip_add_log(&sip_trans->sip_xaction_log[sip_trans->sip_xaction_state],
188 (sip_msg_t)msg, sip_trans->sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
189 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
191 if (sip_msg_info->is_request)
192 return (sip_clnt_xaction_output(conn_obj, sip_trans, msg));
194 ret = sip_srv_xaction_output(conn_obj, sip_trans, msg);
196 return (ret);
200 * Send a Request out
202 static int
203 sip_clnt_xaction_output(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
204 _sip_msg_t *msg)
206 sip_xaction_time_obj_t *timer_obj_A = NULL;
207 sip_xaction_time_obj_t *timer_obj_B = NULL;
208 sip_xaction_time_obj_t *timer_obj_E = NULL;
209 sip_xaction_time_obj_t *timer_obj_F = NULL;
210 sip_message_type_t *sip_msg_info;
211 int prev_state;
212 int error = 0;
213 boolean_t isreliable;
215 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
216 prev_state = sip_trans->sip_xaction_state;
217 if (msg->sip_msg_req_res == NULL) {
218 sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
219 SIP_ASSERT_ERROR, __FILE__, __LINE__);
221 assert(msg->sip_msg_req_res != NULL);
222 sip_msg_info = msg->sip_msg_req_res;
223 isreliable = sip_is_conn_reliable(conn_obj);
225 if (sip_msg_info->sip_req_method == INVITE) {
227 * if transport is not reliable, start TIMER A.
229 if (!isreliable) {
230 timer_obj_A = sip_setup_timer(conn_obj, sip_trans,
231 msg, sip_trans->sip_xaction_TA,
232 SIP_XACTION_TIMER_A);
233 if (timer_obj_A == NULL) {
234 error = ENOMEM;
235 goto error_ret;
239 timer_obj_B = sip_setup_timer(conn_obj, sip_trans, NULL,
240 sip_trans->sip_xaction_TB, SIP_XACTION_TIMER_B);
241 if (timer_obj_B == NULL) {
242 error = ENOMEM;
243 goto error_ret;
245 if (timer_obj_A != NULL) {
246 SIP_SCHED_TIMER(sip_trans->sip_xaction_TA, timer_obj_A,
247 sip_xaction_state_timer_fire);
248 if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TA)) {
249 error = ENOMEM;
250 goto error_ret;
253 SIP_SCHED_TIMER(sip_trans->sip_xaction_TB, timer_obj_B,
254 sip_xaction_state_timer_fire);
255 if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TB)) {
256 if (timer_obj_A != NULL)
257 SIP_CANCEL_TIMER(sip_trans->sip_xaction_TA)
258 error = ENOMEM;
259 goto error_ret;
261 sip_trans->sip_xaction_state = SIP_CLNT_CALLING;
262 } else {
264 * if transport is not reliable, start rexmit Timer E.
266 if (!isreliable) {
267 timer_obj_E = sip_setup_timer(conn_obj, sip_trans, msg,
268 sip_trans->sip_xaction_TE, SIP_XACTION_TIMER_E);
269 if (timer_obj_E == NULL) {
270 error = ENOMEM;
271 goto error_ret;
275 * Start transaction Timer F
277 timer_obj_F = sip_setup_timer(conn_obj, sip_trans, NULL,
278 sip_trans->sip_xaction_TF, SIP_XACTION_TIMER_F);
279 if (timer_obj_F == NULL) {
280 error = ENOMEM;
281 goto error_ret;
283 if (timer_obj_E != NULL) {
284 SIP_SCHED_TIMER(sip_trans->sip_xaction_TE, timer_obj_E,
285 sip_xaction_state_timer_fire);
286 if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TE)) {
287 error = ENOMEM;
288 goto error_ret;
291 SIP_SCHED_TIMER(sip_trans->sip_xaction_TF, timer_obj_F,
292 sip_xaction_state_timer_fire);
293 if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TF)) {
294 if (timer_obj_E != NULL)
295 SIP_CANCEL_TIMER(sip_trans->sip_xaction_TE)
296 error = ENOMEM;
297 goto error_ret;
299 sip_trans->sip_xaction_state = SIP_CLNT_TRYING;
301 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
302 if (sip_xaction_ulp_state_cb != NULL) {
303 sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
304 (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
306 return (0);
308 error_ret:
309 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
310 if (timer_obj_A != NULL)
311 free(timer_obj_A);
312 if (timer_obj_B != NULL)
313 free(timer_obj_B);
314 if (timer_obj_E != NULL)
315 free(timer_obj_E);
316 if (timer_obj_F != NULL)
317 free(timer_obj_F);
318 return (error);
322 * Send a response out
324 static int
325 sip_srv_xaction_output(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
326 _sip_msg_t *msg)
328 int ret;
330 if (sip_trans->sip_xaction_method == INVITE)
331 ret = sip_srv_xaction_inv_res(conn_obj, sip_trans, msg);
332 else
333 ret = sip_srv_xaction_noninv_res(conn_obj, sip_trans, msg);
334 return (ret);
338 * Send a INVITE response out
340 static int
341 sip_srv_xaction_inv_res(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
342 _sip_msg_t *msg)
344 int resp_code;
345 sip_xaction_time_obj_t *timer_obj_G = NULL;
346 sip_xaction_time_obj_t *timer_obj_H = NULL;
347 sip_message_type_t *sip_msg_info = msg->sip_msg_req_res;
348 int prev_state;
349 boolean_t isreliable;
351 isreliable = sip_is_conn_reliable(conn_obj);
353 resp_code = sip_msg_info->sip_resp_code;
354 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
355 prev_state = sip_trans->sip_xaction_state;
356 switch (sip_trans->sip_xaction_state) {
357 case SIP_SRV_INV_PROCEEDING:
358 if (SIP_PROVISIONAL_RESP(resp_code)) {
359 if (sip_trans->sip_xaction_last_msg != NULL) {
360 SIP_MSG_REFCNT_DECR(
361 sip_trans->sip_xaction_last_msg);
362 sip_trans->sip_xaction_last_msg = NULL;
364 SIP_MSG_REFCNT_INCR(msg);
365 sip_trans->sip_xaction_last_msg = msg;
366 (void) sip_add_conn_obj_cache(conn_obj,
367 (void *)sip_trans);
368 } else if (SIP_OK_RESP(resp_code)) {
369 sip_trans->sip_xaction_state =
370 SIP_SRV_INV_TERMINATED;
371 } else if (SIP_NONOK_FINAL_RESP(resp_code)) {
372 if (sip_trans->sip_xaction_last_msg != NULL) {
373 SIP_MSG_REFCNT_DECR(
374 sip_trans->sip_xaction_last_msg);
375 sip_trans->sip_xaction_last_msg = NULL;
377 SIP_MSG_REFCNT_INCR(msg);
378 sip_trans->sip_xaction_last_msg = msg;
379 (void) sip_add_conn_obj_cache(conn_obj,
380 (void *)sip_trans);
382 * For unreliable transport start timer G
384 if (!isreliable) {
385 timer_obj_G = sip_setup_timer(
386 conn_obj, sip_trans,
387 NULL, sip_trans->sip_xaction_TG,
388 SIP_XACTION_TIMER_G);
389 if (timer_obj_G == NULL) {
390 (void) pthread_mutex_unlock(
391 &sip_trans->
392 sip_xaction_mutex);
393 return (ENOMEM);
397 * Start Timer H
399 timer_obj_H = sip_setup_timer(
400 conn_obj, sip_trans,
401 NULL, sip_trans->sip_xaction_TH,
402 SIP_XACTION_TIMER_H);
403 if (timer_obj_H == NULL) {
404 if (timer_obj_G != NULL)
405 free(timer_obj_G);
406 (void) pthread_mutex_unlock(
407 &sip_trans->sip_xaction_mutex);
408 return (ENOMEM);
410 if (timer_obj_G != NULL) {
411 SIP_SCHED_TIMER(
412 sip_trans->sip_xaction_TG,
413 timer_obj_G,
414 sip_xaction_state_timer_fire);
415 if (!SIP_IS_TIMER_RUNNING(
416 sip_trans->sip_xaction_TG)) {
417 (void) pthread_mutex_unlock(
418 &sip_trans->
419 sip_xaction_mutex);
420 free(timer_obj_G);
421 return (ENOMEM);
424 if (timer_obj_H != NULL) {
425 SIP_SCHED_TIMER(
426 sip_trans->sip_xaction_TH,
427 timer_obj_H,
428 sip_xaction_state_timer_fire);
429 if (!SIP_IS_TIMER_RUNNING(
430 sip_trans->sip_xaction_TH)) {
431 if (timer_obj_G != NULL) {
432 SIP_CANCEL_TIMER(
433 sip_trans->
434 sip_xaction_TG);
435 free(timer_obj_G);
437 (void) pthread_mutex_unlock(
438 &sip_trans->
439 sip_xaction_mutex);
440 free(timer_obj_H);
441 return (ENOMEM);
444 sip_trans->sip_xaction_state =
445 SIP_SRV_INV_COMPLETED;
447 break;
448 default:
449 (void) pthread_mutex_unlock(
450 &sip_trans->sip_xaction_mutex);
451 return (EPROTO);
453 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
454 if (prev_state != sip_trans->sip_xaction_state &&
455 sip_xaction_ulp_state_cb != NULL) {
456 sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
457 (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
459 return (0);
463 * Send a NON-INVITE response out
465 static int
466 sip_srv_xaction_noninv_res(sip_conn_object_t conn_obj,
467 sip_xaction_t *sip_trans, _sip_msg_t *msg)
469 int resp_code;
470 sip_xaction_time_obj_t *timer_obj_J = NULL;
471 sip_message_type_t *sip_msg_info = msg->sip_msg_req_res;
472 int prev_state;
473 boolean_t isreliable;
475 resp_code = sip_msg_info->sip_resp_code;
476 isreliable = sip_is_conn_reliable(conn_obj);
478 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
479 prev_state = sip_trans->sip_xaction_state;
480 switch (sip_trans->sip_xaction_state) {
481 case SIP_SRV_TRYING:
482 if (sip_trans->sip_xaction_last_msg != NULL) {
483 SIP_MSG_REFCNT_DECR(
484 sip_trans->sip_xaction_last_msg);
485 sip_trans->sip_xaction_last_msg = NULL;
487 SIP_MSG_REFCNT_INCR(msg);
488 sip_trans->sip_xaction_last_msg = msg;
489 (void) sip_add_conn_obj_cache(conn_obj,
490 (void *)sip_trans);
491 if (SIP_PROVISIONAL_RESP(resp_code)) {
492 sip_trans->sip_xaction_state =
493 SIP_SRV_NONINV_PROCEEDING;
494 } else if (SIP_FINAL_RESP(resp_code)) {
496 * For unreliable transports, start Timer J
498 if (!isreliable) {
499 timer_obj_J = sip_setup_timer(
500 conn_obj, sip_trans,
501 NULL, sip_trans->sip_xaction_TJ,
502 SIP_XACTION_TIMER_J);
503 if (timer_obj_J == NULL) {
504 (void) pthread_mutex_unlock(&
505 sip_trans->
506 sip_xaction_mutex);
507 return (ENOMEM);
509 SIP_SCHED_TIMER(
510 sip_trans->sip_xaction_TJ,
511 timer_obj_J,
512 sip_xaction_state_timer_fire);
513 if (!SIP_IS_TIMER_RUNNING(
514 sip_trans->sip_xaction_TJ)) {
515 (void) pthread_mutex_unlock(&
516 sip_trans->
517 sip_xaction_mutex);
518 free(timer_obj_J);
519 return (ENOMEM);
521 sip_trans->sip_xaction_state =
522 SIP_SRV_NONINV_COMPLETED;
523 } else {
524 sip_trans->sip_xaction_state =
525 SIP_SRV_NONINV_TERMINATED;
528 break;
529 case SIP_SRV_NONINV_PROCEEDING:
530 if (sip_trans->sip_xaction_last_msg != NULL) {
531 SIP_MSG_REFCNT_DECR(
532 sip_trans->sip_xaction_last_msg);
533 sip_trans->sip_xaction_last_msg = NULL;
535 SIP_MSG_REFCNT_INCR(msg);
536 sip_trans->sip_xaction_last_msg = msg;
537 (void) sip_add_conn_obj_cache(conn_obj,
538 (void *)sip_trans);
539 if (SIP_PROVISIONAL_RESP(resp_code)) {
540 break;
541 } else if (SIP_FINAL_RESP(resp_code)) {
543 * For unreliable transports, start Timer J
545 if (!isreliable) {
546 timer_obj_J = sip_setup_timer(
547 conn_obj, sip_trans,
548 NULL, sip_trans->sip_xaction_TJ,
549 SIP_XACTION_TIMER_J);
550 if (timer_obj_J == NULL) {
551 (void) pthread_mutex_unlock(&
552 sip_trans->
553 sip_xaction_mutex);
554 return (ENOMEM);
556 SIP_SCHED_TIMER(
557 sip_trans->sip_xaction_TJ,
558 timer_obj_J,
559 sip_xaction_state_timer_fire);
560 if (!SIP_IS_TIMER_RUNNING(
561 sip_trans->sip_xaction_TJ)) {
562 (void) pthread_mutex_unlock(&
563 sip_trans->
564 sip_xaction_mutex);
565 free(timer_obj_J);
566 return (ENOMEM);
568 sip_trans->sip_xaction_state =
569 SIP_SRV_NONINV_COMPLETED;
570 } else {
571 sip_trans->sip_xaction_state =
572 SIP_SRV_NONINV_TERMINATED;
575 break;
576 default:
577 (void) pthread_mutex_unlock(
578 &sip_trans->sip_xaction_mutex);
579 return (EPROTO);
581 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
582 if (prev_state != sip_trans->sip_xaction_state &&
583 sip_xaction_ulp_state_cb != NULL) {
584 sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
585 (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
587 return (0);
592 * -------------------------- Input Routines ---------------------------
596 * Process an incoming SIP message Request or Response
599 sip_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
600 _sip_msg_t **sip_msg)
602 sip_message_type_t *sip_msg_info;
603 int ret;
605 sip_msg_info = (*sip_msg)->sip_msg_req_res;
607 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
608 sip_trans->sip_xaction_msgcnt++;
609 sip_add_log(&sip_trans->sip_xaction_log[sip_trans->sip_xaction_state],
610 (sip_msg_t)*sip_msg, sip_trans->sip_xaction_msgcnt,
611 SIP_TRANSACTION_LOG);
612 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
614 if (sip_msg_info->is_request)
615 ret = sip_srv_xaction_input(conn_obj, sip_trans, sip_msg);
616 else
617 ret = sip_clnt_xaction_input(conn_obj, sip_trans, sip_msg);
618 return (ret);
622 * Process a Request from the transport
624 static int
625 sip_srv_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
626 _sip_msg_t **sip_msg)
628 sip_message_type_t *sip_msg_info;
629 _sip_msg_t *msg = *sip_msg;
630 int prev_state;
631 boolean_t isreliable;
633 sip_msg_info = msg->sip_msg_req_res;
634 isreliable = sip_is_conn_reliable(conn_obj);
637 * Cancel if the original transaction has not yet got a final
638 * response and send a 487 response.
640 if (sip_msg_info->sip_req_method == ACK) {
641 _sip_msg_t *sip_last_resp;
642 const sip_str_t *resp_to_tag;
643 const sip_str_t *req_to_tag;
644 int error;
645 sip_message_type_t *last_msg_info;
647 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
649 if (sip_trans->sip_xaction_last_msg != NULL)
650 sip_last_resp = sip_trans->sip_xaction_last_msg;
651 else
652 sip_last_resp = sip_trans->sip_xaction_orig_msg;
653 last_msg_info = sip_last_resp->sip_msg_req_res;
654 if (last_msg_info->is_request) {
655 (void) pthread_mutex_unlock(
656 &sip_trans->sip_xaction_mutex);
657 return (0);
659 req_to_tag = sip_get_to_tag((sip_msg_t)msg, &error);
660 if (req_to_tag == NULL || error != 0) {
661 (void) pthread_mutex_unlock(
662 &sip_trans->sip_xaction_mutex);
663 return (0);
665 resp_to_tag = sip_get_to_tag((sip_msg_t)sip_last_resp,
666 &error);
667 if (req_to_tag == NULL || error != 0) {
668 (void) pthread_mutex_unlock(
669 &sip_trans->sip_xaction_mutex);
670 return (0);
672 if (resp_to_tag->sip_str_len != req_to_tag->sip_str_len ||
673 strncmp(resp_to_tag->sip_str_ptr, req_to_tag->sip_str_ptr,
674 req_to_tag->sip_str_len) != 0) {
675 (void) pthread_mutex_unlock(
676 &sip_trans->sip_xaction_mutex);
677 return (0);
679 prev_state = sip_trans->sip_xaction_state;
680 if (sip_trans->sip_xaction_state == SIP_SRV_INV_COMPLETED) {
681 sip_xaction_time_obj_t *timer_obj_I = NULL;
683 SIP_CANCEL_TIMER(sip_trans->sip_xaction_TG);
685 * Cancel Timer H and goto TERMINATED state for
686 * reliable transports.
688 if (isreliable) {
689 SIP_CANCEL_TIMER(
690 sip_trans->sip_xaction_TH);
691 sip_trans->sip_xaction_state =
692 SIP_SRV_INV_TERMINATED;
693 (void) pthread_mutex_unlock(
694 &sip_trans->sip_xaction_mutex);
695 if (sip_xaction_ulp_state_cb != NULL) {
696 sip_xaction_ulp_state_cb(
697 (sip_transaction_t)sip_trans,
698 (sip_msg_t)msg, prev_state,
699 sip_trans->sip_xaction_state);
701 return (0);
704 * For unreliable transports, start TIMER I and
705 * transition to CONFIRMED state.
707 timer_obj_I = sip_setup_timer(conn_obj, sip_trans,
708 NULL,
709 sip_trans->sip_xaction_TI, SIP_XACTION_TIMER_I);
710 if (timer_obj_I == NULL) {
711 (void) pthread_mutex_unlock(
712 &sip_trans->sip_xaction_mutex);
713 return (ENOMEM);
715 SIP_SCHED_TIMER(sip_trans->sip_xaction_TI,
716 timer_obj_I, sip_xaction_state_timer_fire);
717 if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TI)) {
718 (void) pthread_mutex_unlock(
719 &sip_trans->sip_xaction_mutex);
720 free(timer_obj_I);
721 return (ENOMEM);
723 sip_trans->sip_xaction_state = SIP_SRV_CONFIRMED;
725 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
726 if (prev_state != sip_trans->sip_xaction_state &&
727 sip_xaction_ulp_state_cb != NULL) {
728 sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
729 (sip_msg_t)msg, prev_state,
730 sip_trans->sip_xaction_state);
732 return (0);
733 } else if (sip_msg_info->sip_req_method == CANCEL) {
734 if (sip_trans->sip_xaction_method == INVITE) {
735 (void) pthread_mutex_unlock(
736 &sip_trans->sip_xaction_mutex);
737 return (0);
740 if (sip_msg_info->sip_req_method == INVITE) {
741 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
742 if (sip_trans->sip_xaction_method != INVITE) {
743 sip_write_to_log((void *)sip_trans,
744 SIP_TRANSACTION_LOG | SIP_ASSERT_ERROR, __FILE__,
745 __LINE__);
747 assert(sip_trans->sip_xaction_method == INVITE);
749 * Retransmitted invite
751 switch (sip_trans->sip_xaction_state) {
752 case SIP_SRV_INV_PROCEEDING:
753 case SIP_SRV_INV_COMPLETED:
754 if (sip_trans->sip_xaction_last_msg != NULL) {
755 _sip_msg_t *new_msg;
756 sip_message_type_t *msg_info;
757 int resp;
759 new_msg =
760 sip_trans->sip_xaction_last_msg;
761 msg_info = new_msg->sip_msg_req_res;
762 if (msg_info == NULL || msg_info->
763 is_request) {
764 sip_write_to_log((void *)
765 sip_trans,
766 SIP_TRANSACTION_LOG |
767 SIP_ASSERT_ERROR, __FILE__,
768 __LINE__);
770 assert(msg_info != NULL && !msg_info->
771 is_request);
772 resp = msg_info->sip_resp_code;
773 SIP_UPDATE_COUNTERS(B_FALSE, 0, resp,
774 B_TRUE, new_msg->sip_msg_len);
775 ++sip_trans->sip_xaction_msgcnt;
776 sip_add_log(&sip_trans->sip_xaction_log[
777 sip_trans->sip_xaction_state],
778 new_msg, sip_trans->
779 sip_xaction_msgcnt,
780 SIP_TRANSACTION_LOG);
781 (void) sip_stack_send(conn_obj,
782 new_msg->sip_msg_buf,
783 new_msg->sip_msg_len);
785 break;
786 default:
787 (void) pthread_mutex_unlock(
788 &sip_trans->sip_xaction_mutex);
789 return (EPROTO);
791 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
793 * We need to account for this invite received by the stack
794 * before we free that message.
796 SIP_UPDATE_COUNTERS(B_TRUE, INVITE, 0, B_FALSE,
797 msg->sip_msg_len);
798 sip_free_msg((sip_msg_t)msg);
799 *sip_msg = NULL;
800 return (0);
803 * Retransmitted request
805 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
806 if (sip_trans->sip_xaction_method == INVITE) {
807 sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
808 SIP_ASSERT_ERROR, __FILE__, __LINE__);
810 assert(sip_trans->sip_xaction_method != INVITE);
811 switch (sip_trans->sip_xaction_state) {
812 case SIP_SRV_NONINV_PROCEEDING:
813 case SIP_SRV_NONINV_COMPLETED:
814 if (sip_trans->sip_xaction_last_msg != NULL) {
815 _sip_msg_t *new_msg;
816 sip_message_type_t *msg_info;
817 int resp;
819 new_msg = sip_trans->sip_xaction_last_msg;
820 msg_info = new_msg->sip_msg_req_res;
821 if (msg_info == NULL || msg_info->is_request) {
822 sip_write_to_log((void *)sip_trans,
823 SIP_TRANSACTION_LOG |
824 SIP_ASSERT_ERROR, __FILE__,
825 __LINE__);
827 assert(msg_info != NULL && !msg_info->
828 is_request);
829 resp = msg_info->sip_resp_code;
830 SIP_UPDATE_COUNTERS(B_FALSE, 0, resp, B_TRUE,
831 new_msg->sip_msg_len);
832 ++sip_trans->sip_xaction_msgcnt;
833 sip_add_log(&sip_trans->sip_xaction_log[
834 sip_trans->sip_xaction_state], new_msg,
835 sip_trans->sip_xaction_msgcnt,
836 SIP_TRANSACTION_LOG);
837 (void) sip_stack_send(conn_obj,
838 new_msg->sip_msg_buf, new_msg->sip_msg_len);
840 break;
841 default:
842 (void) pthread_mutex_unlock(
843 &sip_trans->sip_xaction_mutex);
844 return (EPROTO);
846 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
848 * We need to account for the retransmitted non-INVITE request here.
849 * When we return from here the msg will be freed and we will not
850 * be able to capture the details at sip_process_new_packet()
852 SIP_UPDATE_COUNTERS(B_TRUE, sip_msg_info->sip_req_method, 0, B_FALSE,
853 msg->sip_msg_len);
854 sip_free_msg((sip_msg_t)msg);
855 *sip_msg = NULL;
856 return (0);
860 * Process a Response
862 static int
863 sip_clnt_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
864 _sip_msg_t **msg)
866 int ret;
868 if (sip_trans->sip_xaction_method == INVITE)
869 ret = sip_clnt_xaction_inv_res(conn_obj, sip_trans, msg);
870 else
871 ret = sip_clnt_xaction_noninv_res(conn_obj, sip_trans, msg);
873 return (ret);
876 static int
877 sip_create_send_nonOKack(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
878 _sip_msg_t *msg, boolean_t copy)
880 _sip_msg_t *ack_msg;
881 int ret = 0;
883 ack_msg = (_sip_msg_t *)sip_new_msg();
884 if (ack_msg == NULL)
885 return (ENOMEM);
886 if ((ret = sip_create_nonOKack(
887 (sip_msg_t)sip_trans->sip_xaction_orig_msg, (sip_msg_t)msg,
888 (sip_msg_t)ack_msg)) != 0) {
889 sip_free_msg((sip_msg_t)ack_msg);
890 return (ret);
892 SIP_UPDATE_COUNTERS(B_TRUE, ACK, 0, B_TRUE, ack_msg->sip_msg_len);
893 ++sip_trans->sip_xaction_msgcnt;
894 sip_add_log(&sip_trans->sip_xaction_log[sip_trans->sip_xaction_state],
895 ack_msg, sip_trans->sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
896 if ((ret = sip_stack_send(conn_obj, ack_msg->sip_msg_buf,
897 ack_msg->sip_msg_len)) != 0) {
898 sip_free_msg((sip_msg_t)ack_msg);
899 return (ret);
901 if (copy) {
902 SIP_MSG_REFCNT_INCR(ack_msg);
903 if (sip_trans->sip_xaction_last_msg != NULL) {
904 SIP_MSG_REFCNT_DECR(sip_trans->sip_xaction_last_msg);
905 sip_trans->sip_xaction_last_msg = NULL;
907 sip_trans->sip_xaction_last_msg = ack_msg;
909 sip_free_msg((sip_msg_t)ack_msg);
910 return (0);
914 * Process a INVITE Response
916 static int
917 sip_clnt_xaction_inv_res(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
918 _sip_msg_t **sip_msg)
920 int resp_code;
921 _sip_msg_t *msg = *sip_msg;
922 sip_xaction_time_obj_t *timer_obj_D = NULL;
923 sip_message_type_t *sip_msg_info;
924 int prev_state;
925 boolean_t isreliable;
927 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
928 if (msg->sip_msg_req_res == NULL) {
929 sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
930 SIP_ASSERT_ERROR, __FILE__, __LINE__);
932 assert(msg->sip_msg_req_res != NULL);
934 sip_msg_info = msg->sip_msg_req_res;
935 resp_code = sip_msg_info->sip_resp_code;
936 isreliable = sip_is_conn_reliable(conn_obj);
938 prev_state = sip_trans->sip_xaction_state;
939 switch (sip_trans->sip_xaction_state) {
940 case SIP_CLNT_CALLING:
941 if (SIP_PROVISIONAL_RESP(resp_code)) {
943 * sip_trans->sip_xaction_last_msg ?
945 SIP_CANCEL_TIMER(
946 sip_trans->sip_xaction_TA);
947 sip_trans->sip_xaction_state =
948 SIP_CLNT_INV_PROCEEDING;
949 } else if (SIP_OK_RESP(resp_code)) {
951 * sip_trans->sip_xaction_last_msg ?
953 SIP_CANCEL_TIMER(
954 sip_trans->sip_xaction_TA);
955 SIP_CANCEL_TIMER(
956 sip_trans->sip_xaction_TB);
957 sip_trans->sip_xaction_state =
958 SIP_CLNT_INV_TERMINATED;
959 } else if (SIP_NONOK_FINAL_RESP(resp_code)) {
960 int ret;
963 * sip_trans->sip_xaction_last_msg ?
965 SIP_CANCEL_TIMER(
966 sip_trans->sip_xaction_TA);
967 SIP_CANCEL_TIMER(
968 sip_trans->sip_xaction_TB);
969 if ((ret = sip_create_send_nonOKack(conn_obj,
970 sip_trans, msg, B_FALSE)) != 0) {
971 (void) pthread_mutex_unlock(
972 &sip_trans->sip_xaction_mutex);
973 return (ret);
976 * start timer D for unreliable transports
978 if (!isreliable) {
979 timer_obj_D = sip_setup_timer(
980 conn_obj, sip_trans,
981 NULL, sip_trans->sip_xaction_TD,
982 SIP_XACTION_TIMER_D);
983 if (timer_obj_D == NULL) {
984 (void) pthread_mutex_unlock(
985 &sip_trans->
986 sip_xaction_mutex);
987 return (ENOMEM);
989 SIP_SCHED_TIMER(
990 sip_trans->sip_xaction_TD,
991 timer_obj_D,
992 sip_xaction_state_timer_fire);
993 if (!SIP_IS_TIMER_RUNNING(
994 sip_trans->sip_xaction_TD)) {
995 (void) pthread_mutex_unlock(
996 &sip_trans->
997 sip_xaction_mutex);
998 free(timer_obj_D);
999 return (ENOMEM);
1001 sip_trans->sip_xaction_state =
1002 SIP_CLNT_INV_COMPLETED;
1003 } else {
1004 sip_trans->sip_xaction_state =
1005 SIP_CLNT_INV_TERMINATED;
1007 } else {
1009 * Invalid resp_code
1011 (void) pthread_mutex_unlock(
1012 &sip_trans->sip_xaction_mutex);
1013 return (EPROTO);
1015 break;
1016 case SIP_CLNT_INV_PROCEEDING:
1017 if (SIP_PROVISIONAL_RESP(resp_code)) {
1018 break;
1019 } else if (SIP_OK_RESP(resp_code)) {
1020 SIP_CANCEL_TIMER(
1021 sip_trans->sip_xaction_TB);
1022 sip_trans->sip_xaction_state =
1023 SIP_CLNT_INV_TERMINATED;
1024 } else if (SIP_NONOK_FINAL_RESP(resp_code)) {
1025 int ret;
1027 SIP_CANCEL_TIMER(
1028 sip_trans->sip_xaction_TB);
1029 if ((ret = sip_create_send_nonOKack(conn_obj,
1030 sip_trans, msg, B_FALSE)) != 0) {
1031 (void) pthread_mutex_unlock(
1032 &sip_trans->sip_xaction_mutex);
1033 return (ret);
1036 * start timer D for unreliable transports
1038 if (!isreliable) {
1039 timer_obj_D = sip_setup_timer(
1040 conn_obj, sip_trans,
1041 NULL, sip_trans->sip_xaction_TD,
1042 SIP_XACTION_TIMER_D);
1043 if (timer_obj_D == NULL) {
1044 (void) pthread_mutex_unlock(
1045 &sip_trans->
1046 sip_xaction_mutex);
1047 return (ENOMEM);
1049 SIP_SCHED_TIMER(
1050 sip_trans->sip_xaction_TD,
1051 timer_obj_D,
1052 sip_xaction_state_timer_fire);
1053 if (!SIP_IS_TIMER_RUNNING(
1054 sip_trans->sip_xaction_TD)) {
1055 (void) pthread_mutex_unlock(
1056 &sip_trans->
1057 sip_xaction_mutex);
1058 free(timer_obj_D);
1059 return (ENOMEM);
1061 sip_trans->sip_xaction_state =
1062 SIP_CLNT_INV_COMPLETED;
1063 } else {
1064 sip_trans->sip_xaction_state =
1065 SIP_CLNT_INV_TERMINATED;
1067 } else {
1068 (void) pthread_mutex_unlock(
1069 &sip_trans->sip_xaction_mutex);
1070 return (EPROTO);
1072 break;
1073 case SIP_CLNT_INV_COMPLETED:
1075 * Transport error takes it to
1076 * SIP_CLNT_INV_TERMINATED
1078 if (SIP_NONOK_FINAL_RESP(resp_code)) {
1079 int ret;
1081 if ((ret = sip_create_send_nonOKack(conn_obj,
1082 sip_trans, msg, B_FALSE)) != 0) {
1083 (void) pthread_mutex_unlock(
1084 &sip_trans->sip_xaction_mutex);
1085 return (ret);
1087 } else {
1089 * Invalid resp_code
1091 (void) pthread_mutex_unlock(
1092 &sip_trans->sip_xaction_mutex);
1093 return (EPROTO);
1095 break;
1096 default:
1097 (void) pthread_mutex_unlock(
1098 &sip_trans->sip_xaction_mutex);
1099 return (EPROTO);
1101 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
1102 if (prev_state != sip_trans->sip_xaction_state &&
1103 sip_xaction_ulp_state_cb != NULL) {
1104 sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
1105 (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
1107 return (0);
1111 * Process a NON-INVITE Response
1113 static int
1114 sip_clnt_xaction_noninv_res(sip_conn_object_t conn_obj,
1115 sip_xaction_t *sip_trans, _sip_msg_t **sip_msg)
1117 int resp_code;
1118 sip_xaction_time_obj_t *timer_obj_K = NULL;
1119 sip_message_type_t *sip_msg_info;
1120 int prev_state;
1121 _sip_msg_t *msg = *sip_msg;
1122 boolean_t isreliable;
1124 if (msg->sip_msg_req_res == NULL || sip_trans == NULL) {
1125 sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
1126 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1128 assert(msg->sip_msg_req_res != NULL);
1129 assert(sip_trans != NULL);
1131 sip_msg_info = msg->sip_msg_req_res;
1132 isreliable = sip_is_conn_reliable(conn_obj);
1133 resp_code = sip_msg_info->sip_resp_code;
1134 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
1135 prev_state = sip_trans->sip_xaction_state;
1136 switch (sip_trans->sip_xaction_state) {
1137 case SIP_CLNT_TRYING:
1138 if (SIP_PROVISIONAL_RESP(resp_code)) {
1139 sip_trans->sip_xaction_state =
1140 SIP_CLNT_NONINV_PROCEEDING;
1141 } else if (SIP_FINAL_RESP(resp_code)) {
1142 SIP_CANCEL_TIMER(
1143 sip_trans->sip_xaction_TE);
1144 SIP_CANCEL_TIMER(
1145 sip_trans->sip_xaction_TF);
1147 * Start timer K for unreliable transports
1149 if (!isreliable) {
1150 timer_obj_K = sip_setup_timer(
1151 conn_obj, sip_trans,
1152 NULL, sip_trans->sip_xaction_TK,
1153 SIP_XACTION_TIMER_K);
1154 if (timer_obj_K == NULL) {
1155 (void) pthread_mutex_unlock(&
1156 sip_trans->
1157 sip_xaction_mutex);
1158 return (ENOMEM);
1160 SIP_SCHED_TIMER(
1161 sip_trans->sip_xaction_TK,
1162 timer_obj_K,
1163 sip_xaction_state_timer_fire);
1164 if (!SIP_IS_TIMER_RUNNING(
1165 sip_trans->sip_xaction_TK)) {
1166 (void) pthread_mutex_unlock(
1167 &sip_trans->
1168 sip_xaction_mutex);
1169 free(timer_obj_K);
1170 return (ENOMEM);
1172 sip_trans->sip_xaction_state =
1173 SIP_CLNT_NONINV_COMPLETED;
1174 } else {
1175 sip_trans->sip_xaction_state =
1176 SIP_CLNT_NONINV_TERMINATED;
1179 break;
1180 case SIP_CLNT_NONINV_PROCEEDING:
1181 if (SIP_PROVISIONAL_RESP(resp_code)) {
1182 break;
1183 } else if (SIP_FINAL_RESP(resp_code)) {
1184 SIP_CANCEL_TIMER(
1185 sip_trans->sip_xaction_TE);
1186 SIP_CANCEL_TIMER(
1187 sip_trans->sip_xaction_TF);
1189 * Start timer K for unreliable transports
1191 if (!isreliable) {
1192 timer_obj_K = sip_setup_timer(
1193 conn_obj, sip_trans,
1194 NULL, sip_trans->sip_xaction_TK,
1195 SIP_XACTION_TIMER_K);
1196 if (timer_obj_K == NULL) {
1197 (void) pthread_mutex_unlock(&
1198 sip_trans->
1199 sip_xaction_mutex);
1200 return (ENOMEM);
1202 SIP_SCHED_TIMER(
1203 sip_trans->sip_xaction_TK,
1204 timer_obj_K,
1205 sip_xaction_state_timer_fire);
1206 if (!SIP_IS_TIMER_RUNNING(
1207 sip_trans->sip_xaction_TK)) {
1208 (void) pthread_mutex_unlock(
1209 &sip_trans->
1210 sip_xaction_mutex);
1211 free(timer_obj_K);
1212 return (ENOMEM);
1214 sip_trans->sip_xaction_state =
1215 SIP_CLNT_NONINV_COMPLETED;
1216 } else {
1217 sip_trans->sip_xaction_state =
1218 SIP_CLNT_NONINV_TERMINATED;
1221 break;
1222 default:
1223 (void) pthread_mutex_unlock(
1224 &sip_trans->sip_xaction_mutex);
1225 return (EPROTO);
1227 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
1228 if (prev_state != sip_trans->sip_xaction_state &&
1229 sip_xaction_ulp_state_cb != NULL) {
1230 sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
1231 (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
1233 return (0);
1237 * If there is a transport error, sending the message out, terminate the
1238 * transaction.
1240 /* ARGSUSED */
1241 void
1242 sip_xaction_terminate(sip_xaction_t *sip_trans, _sip_msg_t *msg, int transport)
1244 sip_message_type_t *sip_msg_info;
1245 int state;
1246 int prev_state;
1248 sip_msg_info = msg->sip_msg_req_res;
1249 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
1250 if (sip_msg_info->is_request) {
1251 if (sip_trans->sip_xaction_method == INVITE)
1252 state = SIP_CLNT_INV_TERMINATED;
1253 else
1254 state = SIP_CLNT_NONINV_TERMINATED;
1255 } else {
1256 if (sip_trans->sip_xaction_method == INVITE)
1257 state = SIP_SRV_INV_TERMINATED;
1258 else
1259 state = SIP_SRV_NONINV_TERMINATED;
1261 prev_state = sip_trans->sip_xaction_state;
1262 sip_trans->sip_xaction_state = state;
1263 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
1264 if (sip_xaction_ulp_state_cb != NULL) {
1265 sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
1266 (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
1268 sip_xaction_delete(sip_trans);
1272 * --------------------------- Timer Routine ---------------------------
1275 void
1276 sip_xaction_state_timer_fire(void *args)
1278 sip_xaction_time_obj_t *time_obj = (sip_xaction_time_obj_t *)args;
1279 sip_xaction_t *sip_trans = time_obj->sip_trans;
1280 _sip_msg_t *new_msg;
1281 boolean_t destroy_trans = B_FALSE;
1282 sip_conn_object_t conn_obj;
1283 int prev_state;
1284 sip_message_type_t *msg_info;
1285 int resp;
1286 sip_method_t method;
1288 assert(time_obj != NULL);
1290 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
1291 prev_state = sip_trans->sip_xaction_state;
1292 switch (time_obj->sip_xaction_timer_type) {
1293 case SIP_XACTION_TIMER_A:
1294 if (sip_trans->sip_xaction_state != SIP_CLNT_CALLING)
1295 break;
1297 * Assert candidate
1299 if (sip_trans->sip_xaction_last_msg == NULL)
1300 break;
1301 if (sip_trans->sip_xaction_conn_obj == NULL)
1302 break;
1303 new_msg = sip_trans->sip_xaction_last_msg;
1304 conn_obj = sip_trans->sip_xaction_conn_obj;
1305 /* timer A is for INVITE-RETRANSMIT only */
1306 SIP_UPDATE_COUNTERS(B_TRUE, INVITE, 0, B_TRUE, new_msg->
1307 sip_msg_len);
1308 ++sip_trans->sip_xaction_msgcnt;
1309 sip_add_log(&sip_trans->sip_xaction_log[sip_trans->
1310 sip_xaction_state], new_msg, sip_trans->
1311 sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
1312 if (sip_stack_send(conn_obj, new_msg->sip_msg_buf,
1313 new_msg->sip_msg_len) != 0) {
1314 sip_del_conn_obj_cache(
1315 sip_trans->sip_xaction_conn_obj,
1316 (void *)sip_trans);
1317 sip_trans->sip_xaction_state =
1318 SIP_CLNT_INV_TERMINATED;
1319 (void) pthread_mutex_unlock(
1320 &sip_trans->sip_xaction_mutex);
1321 if (sip_xaction_ulp_state_cb != NULL) {
1322 sip_xaction_ulp_state_cb(
1323 (sip_transaction_t)sip_trans, NULL,
1324 prev_state, sip_trans->
1325 sip_xaction_state);
1327 if (sip_xaction_ulp_trans_err != NULL) {
1328 sip_xaction_ulp_trans_err(sip_trans, 0,
1329 NULL);
1331 sip_xaction_delete(sip_trans);
1332 free(time_obj);
1333 return;
1335 SIP_SET_TIMEOUT(sip_trans->sip_xaction_TA,
1336 2 * SIP_GET_TIMEOUT(sip_trans->sip_xaction_TA));
1338 * Reschedule the timer
1340 SIP_SCHED_TIMER(sip_trans->sip_xaction_TA,
1341 time_obj, sip_xaction_state_timer_fire);
1342 if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TA)) {
1343 sip_del_conn_obj_cache(
1344 sip_trans->sip_xaction_conn_obj,
1345 (void *)sip_trans);
1346 sip_trans->sip_xaction_state =
1347 SIP_CLNT_INV_TERMINATED;
1348 (void) pthread_mutex_unlock(
1349 &sip_trans->sip_xaction_mutex);
1350 if (sip_xaction_ulp_state_cb != NULL) {
1351 sip_xaction_ulp_state_cb(
1352 (sip_transaction_t)sip_trans, NULL,
1353 prev_state, sip_trans->
1354 sip_xaction_state);
1356 if (sip_xaction_ulp_trans_err != NULL) {
1357 sip_xaction_ulp_trans_err(sip_trans, 0,
1358 NULL);
1360 sip_xaction_delete(sip_trans);
1361 free(time_obj);
1362 return;
1364 (void) pthread_mutex_unlock(
1365 &sip_trans->sip_xaction_mutex);
1366 return;
1367 case SIP_XACTION_TIMER_B:
1368 SIP_CANCEL_TIMER(sip_trans->sip_xaction_TA);
1369 if (sip_trans->sip_xaction_state == SIP_CLNT_CALLING) {
1370 sip_trans->sip_xaction_state =
1371 SIP_CLNT_INV_TERMINATED;
1372 (void) pthread_mutex_unlock(
1373 &sip_trans->sip_xaction_mutex);
1374 if (sip_xaction_ulp_state_cb != NULL) {
1375 sip_xaction_ulp_state_cb(
1376 (sip_transaction_t)sip_trans, NULL,
1377 prev_state, sip_trans->
1378 sip_xaction_state);
1380 if (sip_xaction_ulp_trans_err != NULL) {
1381 sip_xaction_ulp_trans_err(sip_trans, 0,
1382 NULL);
1384 sip_xaction_delete(sip_trans);
1385 free(time_obj);
1386 return;
1388 break;
1389 case SIP_XACTION_TIMER_D:
1390 if (sip_trans->sip_xaction_state ==
1391 SIP_CLNT_INV_COMPLETED) {
1392 SIP_CANCEL_TIMER(
1393 sip_trans->sip_xaction_TB);
1394 sip_trans->sip_xaction_state =
1395 SIP_CLNT_INV_TERMINATED;
1396 destroy_trans = B_TRUE;
1398 break;
1399 case SIP_XACTION_TIMER_E:
1401 * Assert candidate
1403 if (sip_trans->sip_xaction_state != SIP_CLNT_TRYING &&
1404 sip_trans->sip_xaction_state !=
1405 SIP_CLNT_NONINV_PROCEEDING) {
1406 break;
1409 * Assert candidate
1411 if (sip_trans->sip_xaction_last_msg == NULL)
1412 break;
1413 if (sip_trans->sip_xaction_conn_obj == NULL)
1414 break;
1415 conn_obj = sip_trans->sip_xaction_conn_obj;
1416 new_msg = sip_trans->sip_xaction_last_msg;
1417 /* Timer E is for non-INVITE request */
1419 msg_info = new_msg->sip_msg_req_res;
1420 if (msg_info == NULL || !msg_info->is_request) {
1421 (void) sip_write_to_log((void *) sip_trans,
1422 SIP_TRANSACTION_LOG | SIP_ASSERT_ERROR,
1423 __FILE__, __LINE__);
1425 assert(msg_info != NULL && msg_info->is_request);
1426 method = msg_info->sip_req_method;
1427 SIP_UPDATE_COUNTERS(B_TRUE, method, 0, B_TRUE, new_msg->
1428 sip_msg_len);
1429 ++sip_trans->sip_xaction_msgcnt;
1430 sip_add_log(&sip_trans->sip_xaction_log[sip_trans->
1431 sip_xaction_state], new_msg, sip_trans->
1432 sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
1433 if (sip_stack_send(conn_obj, new_msg->sip_msg_buf,
1434 new_msg->sip_msg_len) != 0) {
1435 sip_del_conn_obj_cache(
1436 sip_trans->sip_xaction_conn_obj,
1437 (void *)sip_trans);
1438 sip_trans->sip_xaction_state =
1439 SIP_CLNT_NONINV_TERMINATED;
1440 (void) pthread_mutex_unlock(
1441 &sip_trans->sip_xaction_mutex);
1442 if (sip_xaction_ulp_state_cb != NULL) {
1443 sip_xaction_ulp_state_cb(
1444 (sip_transaction_t)sip_trans, NULL,
1445 prev_state, sip_trans->
1446 sip_xaction_state);
1448 if (sip_xaction_ulp_trans_err != NULL) {
1449 sip_xaction_ulp_trans_err(sip_trans, 0,
1450 NULL);
1452 sip_xaction_delete(sip_trans);
1453 free(time_obj);
1454 return;
1456 SIP_SET_TIMEOUT(sip_trans->sip_xaction_TE,
1457 MIN(SIP_TIMER_T2,
1458 2 * SIP_GET_TIMEOUT(sip_trans->sip_xaction_TE)));
1460 * Reschedule the timer
1462 SIP_SCHED_TIMER(sip_trans->sip_xaction_TE,
1463 time_obj, sip_xaction_state_timer_fire);
1464 if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TE)) {
1465 sip_del_conn_obj_cache(
1466 sip_trans->sip_xaction_conn_obj,
1467 (void *)sip_trans);
1468 sip_trans->sip_xaction_state =
1469 SIP_CLNT_NONINV_TERMINATED;
1470 (void) pthread_mutex_unlock(
1471 &sip_trans->sip_xaction_mutex);
1472 if (sip_xaction_ulp_state_cb != NULL) {
1473 sip_xaction_ulp_state_cb(
1474 (sip_transaction_t)sip_trans, NULL,
1475 prev_state, sip_trans->
1476 sip_xaction_state);
1478 if (sip_xaction_ulp_trans_err != NULL) {
1479 sip_xaction_ulp_trans_err(sip_trans, 0,
1480 NULL);
1482 sip_xaction_delete(sip_trans);
1483 free(time_obj);
1484 return;
1486 (void) pthread_mutex_unlock(
1487 &sip_trans->sip_xaction_mutex);
1488 return;
1489 case SIP_XACTION_TIMER_F:
1490 SIP_CANCEL_TIMER(sip_trans->sip_xaction_TE);
1491 if (sip_trans->sip_xaction_state == SIP_CLNT_TRYING ||
1492 sip_trans->sip_xaction_state ==
1493 SIP_CLNT_NONINV_PROCEEDING) {
1494 sip_trans->sip_xaction_state =
1495 SIP_CLNT_NONINV_TERMINATED;
1496 (void) pthread_mutex_unlock(
1497 &sip_trans->sip_xaction_mutex);
1498 if (sip_xaction_ulp_state_cb != NULL) {
1499 sip_xaction_ulp_state_cb(
1500 (sip_transaction_t)sip_trans, NULL,
1501 prev_state, sip_trans->
1502 sip_xaction_state);
1504 if (sip_xaction_ulp_trans_err != NULL) {
1505 sip_xaction_ulp_trans_err(sip_trans, 0,
1506 NULL);
1508 sip_xaction_delete(sip_trans);
1509 free(time_obj);
1510 return;
1512 break;
1513 case SIP_XACTION_TIMER_G:
1515 * Assert candidate
1517 if (sip_trans->sip_xaction_last_msg == NULL)
1518 break;
1519 if (sip_trans->sip_xaction_conn_obj == NULL)
1520 break;
1521 if (sip_trans->sip_xaction_state !=
1522 SIP_SRV_INV_COMPLETED) {
1523 break;
1525 new_msg = sip_trans->sip_xaction_last_msg;
1526 conn_obj = sip_trans->sip_xaction_conn_obj;
1527 msg_info = new_msg->sip_msg_req_res;
1528 if (msg_info == NULL || msg_info->is_request) {
1529 (void) sip_write_to_log((void *) sip_trans,
1530 SIP_TRANSACTION_LOG | SIP_ASSERT_ERROR,
1531 __FILE__, __LINE__);
1533 assert(msg_info != NULL && !msg_info->is_request);
1534 resp = msg_info->sip_resp_code;
1535 SIP_UPDATE_COUNTERS(B_FALSE, 0, resp, B_TRUE, new_msg->
1536 sip_msg_len);
1537 ++sip_trans->sip_xaction_msgcnt;
1538 sip_add_log(&sip_trans->sip_xaction_log[sip_trans->
1539 sip_xaction_state], new_msg, sip_trans->
1540 sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
1541 if (sip_stack_send(conn_obj, new_msg->sip_msg_buf,
1542 new_msg->sip_msg_len) != 0) {
1543 sip_del_conn_obj_cache(
1544 sip_trans->sip_xaction_conn_obj,
1545 (void *)sip_trans);
1546 sip_trans->sip_xaction_state =
1547 SIP_SRV_INV_TERMINATED;
1548 (void) pthread_mutex_unlock(
1549 &sip_trans->sip_xaction_mutex);
1550 if (sip_xaction_ulp_state_cb != NULL) {
1551 sip_xaction_ulp_state_cb(
1552 (sip_transaction_t)sip_trans, NULL,
1553 prev_state, sip_trans->
1554 sip_xaction_state);
1556 if (sip_xaction_ulp_trans_err != NULL) {
1557 sip_xaction_ulp_trans_err(sip_trans, 0,
1558 NULL);
1560 sip_xaction_delete(sip_trans);
1561 free(time_obj);
1562 return;
1564 SIP_SET_TIMEOUT(sip_trans->sip_xaction_TG,
1565 MIN(SIP_TIMER_T2,
1566 2 * SIP_GET_TIMEOUT(sip_trans->sip_xaction_TG)));
1567 SIP_SCHED_TIMER(sip_trans->sip_xaction_TG,
1568 time_obj, sip_xaction_state_timer_fire);
1569 if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TG)) {
1570 sip_del_conn_obj_cache(
1571 sip_trans->sip_xaction_conn_obj,
1572 (void *)sip_trans);
1573 sip_trans->sip_xaction_state =
1574 SIP_SRV_INV_TERMINATED;
1575 (void) pthread_mutex_unlock(
1576 &sip_trans->sip_xaction_mutex);
1577 if (sip_xaction_ulp_state_cb != NULL) {
1578 sip_xaction_ulp_state_cb(
1579 (sip_transaction_t)sip_trans, NULL,
1580 prev_state, sip_trans->
1581 sip_xaction_state);
1583 if (sip_xaction_ulp_trans_err != NULL) {
1584 sip_xaction_ulp_trans_err(sip_trans, 0,
1585 NULL);
1587 sip_xaction_delete(sip_trans);
1588 free(time_obj);
1589 return;
1591 (void) pthread_mutex_unlock(
1592 &sip_trans->sip_xaction_mutex);
1593 return;
1594 case SIP_XACTION_TIMER_H:
1595 SIP_CANCEL_TIMER(sip_trans->sip_xaction_TG);
1596 if (sip_trans->sip_xaction_state ==
1597 SIP_SRV_INV_COMPLETED) {
1598 sip_trans->sip_xaction_state =
1599 SIP_SRV_INV_TERMINATED;
1600 (void) pthread_mutex_unlock(
1601 &sip_trans->sip_xaction_mutex);
1602 if (sip_xaction_ulp_state_cb != NULL) {
1603 sip_xaction_ulp_state_cb(
1604 (sip_transaction_t)sip_trans, NULL,
1605 prev_state, sip_trans->
1606 sip_xaction_state);
1608 if (sip_xaction_ulp_trans_err != NULL) {
1609 sip_xaction_ulp_trans_err(sip_trans, 0,
1610 NULL);
1612 sip_xaction_delete(sip_trans);
1613 free(time_obj);
1614 return;
1616 break;
1617 case SIP_XACTION_TIMER_I:
1618 if (sip_trans->sip_xaction_state ==
1619 SIP_SRV_CONFIRMED) {
1620 SIP_CANCEL_TIMER(
1621 sip_trans->sip_xaction_TH);
1622 sip_trans->sip_xaction_state =
1623 SIP_SRV_INV_TERMINATED;
1624 destroy_trans = B_TRUE;
1626 break;
1627 case SIP_XACTION_TIMER_J:
1628 if (sip_trans->sip_xaction_state ==
1629 SIP_SRV_NONINV_COMPLETED) {
1630 sip_trans->sip_xaction_state =
1631 SIP_SRV_NONINV_TERMINATED;
1632 destroy_trans = B_TRUE;
1635 break;
1636 case SIP_XACTION_TIMER_K:
1637 if (sip_trans->sip_xaction_state ==
1638 SIP_CLNT_NONINV_COMPLETED) {
1639 SIP_CANCEL_TIMER(
1640 sip_trans->sip_xaction_TF);
1641 sip_trans->sip_xaction_state =
1642 SIP_CLNT_NONINV_TERMINATED;
1643 destroy_trans = B_TRUE;
1645 break;
1646 default:
1647 break;
1649 if (destroy_trans) {
1650 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
1651 if (sip_xaction_ulp_state_cb != NULL &&
1652 prev_state != sip_trans->sip_xaction_state) {
1653 sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
1654 NULL, prev_state, sip_trans->sip_xaction_state);
1656 sip_xaction_delete(sip_trans);
1657 free(time_obj);
1658 return;
1660 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
1661 if (sip_xaction_ulp_state_cb != NULL &&
1662 prev_state != sip_trans->sip_xaction_state) {
1663 sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans, NULL,
1664 prev_state, sip_trans->sip_xaction_state);
1666 free(time_obj);