dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libsip / common / sip_xaction_state_mc.c
blobed6d406c14c67e08f3654750b21dd2fe9783a524
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.
28 * SIP Client/Server Invite/Non-Invite Transaction State machine.
31 #include <stdlib.h>
32 #include <string.h>
33 #include <assert.h>
34 #include <errno.h>
35 #include <pthread.h>
36 #include <sip.h>
38 #include "sip_miscdefs.h"
39 #include "sip_msg.h"
40 #include "sip_xaction.h"
43 * Some Timer related info from RFC 3261, page 265.
45 * ----------------------------------------------------------------------
46 * Timer Value Section Meaning
47 * ----------------------------------------------------------------------
48 * T1 500ms default Section 17.1.1.1 RTT Estimate
49 * T2 4s Section 17.1.2.2 The maximum retransmit
50 * interval for non-INVITE
51 * requests and INVITE
52 * responses
53 * T4 5s Section 17.1.2.2 Maximum duration a
54 * message will
55 * remain in the network
56 * ----------------------------------------------------------------------
57 * Timer A initially T1 Section 17.1.1.2 INVITE request retransmit
58 * interval, for UDP only
59 * Timer B 64*T1 Section 17.1.1.2 INVITE transaction
60 * timeout timer
61 * Timer C > 3min Section 16.6 proxy INVITE transaction
62 * bullet 11 timeout
63 * Timer D > 32s for UDP Section 17.1.1.2 Wait time for response
64 * 0s for TCP/SCTP retransmits
65 * Timer E initially T1 Section 17.1.2.2 non-INVITE request
66 * retransmit interval,
67 * UDP only
68 * Timer F 64*T1 Section 17.1.2.2 non-INVITE transaction
69 * timeout timer
70 * Timer G initially T1 Section 17.2.1 INVITE response
71 * retransmit interval
72 * Timer H 64*T1 Section 17.2.1 Wait time for
73 * ACK receipt
74 * Timer I T4 for UDP Section 17.2.1 Wait time for
75 * 0s for TCP/SCTP ACK retransmits
76 * Timer J 64*T1 for UDP Section 17.2.2 Wait time for
77 * 0s for TCP/SCTP non-INVITE request
78 * retransmits
79 * Timer K T4 for UDP Section 17.1.2.2 Wait time for
80 * 0s for TCP/SCTP response retransmits
81 * ----------------------------------------------------------------------
84 #ifndef MIN
85 #define MIN(a, b) (((a) < (b)) ? (a):(b))
86 #endif
89 * Arg to the timer fire routine
91 typedef struct sip_xaction_timer_obj_s {
92 sip_xaction_timer_type_t sip_xaction_timer_type;
93 sip_xaction_t *sip_trans;
94 int sip_xaction_timer_xport;
95 } sip_xaction_time_obj_t;
97 int sip_xaction_output(sip_conn_object_t, sip_xaction_t *,
98 _sip_msg_t *);
99 int sip_xaction_input(sip_conn_object_t, sip_xaction_t *,
100 _sip_msg_t **);
101 void sip_xaction_terminate(sip_xaction_t *, _sip_msg_t *, int);
103 static int sip_clnt_xaction_output(sip_conn_object_t, sip_xaction_t *,
104 _sip_msg_t *);
105 static int sip_clnt_xaction_input(sip_conn_object_t, sip_xaction_t *,
106 _sip_msg_t **);
107 static int sip_clnt_xaction_inv_res(sip_conn_object_t, sip_xaction_t *,
108 _sip_msg_t **);
109 static int sip_clnt_xaction_noninv_res(sip_conn_object_t, sip_xaction_t *,
110 _sip_msg_t **);
111 static int sip_srv_xaction_output(sip_conn_object_t, sip_xaction_t *,
112 _sip_msg_t *);
113 static int sip_srv_xaction_input(sip_conn_object_t, sip_xaction_t *,
114 _sip_msg_t **);
115 static int sip_srv_xaction_inv_res(sip_conn_object_t, sip_xaction_t *,
116 _sip_msg_t *);
117 static int sip_srv_xaction_noninv_res(sip_conn_object_t, sip_xaction_t *,
118 _sip_msg_t *);
119 static int sip_create_send_nonOKack(sip_conn_object_t, sip_xaction_t *,
120 _sip_msg_t *, boolean_t);
121 void sip_xaction_state_timer_fire(void *);
123 static sip_xaction_time_obj_t *sip_setup_timer(sip_conn_object_t,
124 sip_xaction_t *, _sip_msg_t *,
125 sip_timer_t, int);
128 * Return a timer object
130 static sip_xaction_time_obj_t *
131 sip_setup_timer(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
132 _sip_msg_t *sip_msg, sip_timer_t timer, int type)
134 sip_xaction_time_obj_t *sip_timer_obj = NULL;
136 sip_timer_obj = (sip_xaction_time_obj_t *)
137 malloc(sizeof (sip_xaction_time_obj_t));
138 if (sip_timer_obj == NULL)
139 return (NULL);
140 if (SIP_IS_TIMER_RUNNING(timer))
141 SIP_CANCEL_TIMER(timer);
142 sip_timer_obj->sip_xaction_timer_type = type;
143 sip_timer_obj->sip_xaction_timer_xport = sip_conn_transport(conn_obj);
144 sip_timer_obj->sip_trans = sip_trans;
146 * Save the message
148 if (sip_msg != NULL) {
149 (void) sip_add_conn_obj_cache(conn_obj, (void *)sip_trans);
150 if (sip_trans->sip_xaction_last_msg != NULL) {
151 SIP_MSG_REFCNT_DECR(sip_trans->sip_xaction_last_msg);
152 sip_trans->sip_xaction_last_msg = NULL;
154 SIP_MSG_REFCNT_INCR(sip_msg);
155 sip_trans->sip_xaction_last_msg = sip_msg;
157 return (sip_timer_obj);
161 * --------------------------- Output Routines ---------------------------
165 * Send a SIP message, request or response, out
168 sip_xaction_output(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
169 _sip_msg_t *msg)
171 sip_message_type_t *sip_msg_info;
172 int ret;
174 if (conn_obj == NULL) {
175 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
176 sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
177 SIP_ASSERT_ERROR, __FILE__, __LINE__);
178 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
180 assert(conn_obj != NULL);
181 sip_msg_info = msg->sip_msg_req_res;
183 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
184 sip_trans->sip_xaction_msgcnt++;
185 sip_add_log(&sip_trans->sip_xaction_log[sip_trans->sip_xaction_state],
186 (sip_msg_t)msg, sip_trans->sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
187 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
189 if (sip_msg_info->is_request)
190 return (sip_clnt_xaction_output(conn_obj, sip_trans, msg));
192 ret = sip_srv_xaction_output(conn_obj, sip_trans, msg);
194 return (ret);
198 * Send a Request out
200 static int
201 sip_clnt_xaction_output(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
202 _sip_msg_t *msg)
204 sip_xaction_time_obj_t *timer_obj_A = NULL;
205 sip_xaction_time_obj_t *timer_obj_B = NULL;
206 sip_xaction_time_obj_t *timer_obj_E = NULL;
207 sip_xaction_time_obj_t *timer_obj_F = NULL;
208 sip_message_type_t *sip_msg_info;
209 int prev_state;
210 int error = 0;
211 boolean_t isreliable;
213 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
214 prev_state = sip_trans->sip_xaction_state;
215 if (msg->sip_msg_req_res == NULL) {
216 sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
217 SIP_ASSERT_ERROR, __FILE__, __LINE__);
219 assert(msg->sip_msg_req_res != NULL);
220 sip_msg_info = msg->sip_msg_req_res;
221 isreliable = sip_is_conn_reliable(conn_obj);
223 if (sip_msg_info->sip_req_method == INVITE) {
225 * if transport is not reliable, start TIMER A.
227 if (!isreliable) {
228 timer_obj_A = sip_setup_timer(conn_obj, sip_trans,
229 msg, sip_trans->sip_xaction_TA,
230 SIP_XACTION_TIMER_A);
231 if (timer_obj_A == NULL) {
232 error = ENOMEM;
233 goto error_ret;
237 timer_obj_B = sip_setup_timer(conn_obj, sip_trans, NULL,
238 sip_trans->sip_xaction_TB, SIP_XACTION_TIMER_B);
239 if (timer_obj_B == NULL) {
240 error = ENOMEM;
241 goto error_ret;
243 if (timer_obj_A != NULL) {
244 SIP_SCHED_TIMER(sip_trans->sip_xaction_TA, timer_obj_A,
245 sip_xaction_state_timer_fire);
246 if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TA)) {
247 error = ENOMEM;
248 goto error_ret;
251 SIP_SCHED_TIMER(sip_trans->sip_xaction_TB, timer_obj_B,
252 sip_xaction_state_timer_fire);
253 if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TB)) {
254 if (timer_obj_A != NULL)
255 SIP_CANCEL_TIMER(sip_trans->sip_xaction_TA)
256 error = ENOMEM;
257 goto error_ret;
259 sip_trans->sip_xaction_state = SIP_CLNT_CALLING;
260 } else {
262 * if transport is not reliable, start rexmit Timer E.
264 if (!isreliable) {
265 timer_obj_E = sip_setup_timer(conn_obj, sip_trans, msg,
266 sip_trans->sip_xaction_TE, SIP_XACTION_TIMER_E);
267 if (timer_obj_E == NULL) {
268 error = ENOMEM;
269 goto error_ret;
273 * Start transaction Timer F
275 timer_obj_F = sip_setup_timer(conn_obj, sip_trans, NULL,
276 sip_trans->sip_xaction_TF, SIP_XACTION_TIMER_F);
277 if (timer_obj_F == NULL) {
278 error = ENOMEM;
279 goto error_ret;
281 if (timer_obj_E != NULL) {
282 SIP_SCHED_TIMER(sip_trans->sip_xaction_TE, timer_obj_E,
283 sip_xaction_state_timer_fire);
284 if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TE)) {
285 error = ENOMEM;
286 goto error_ret;
289 SIP_SCHED_TIMER(sip_trans->sip_xaction_TF, timer_obj_F,
290 sip_xaction_state_timer_fire);
291 if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TF)) {
292 if (timer_obj_E != NULL)
293 SIP_CANCEL_TIMER(sip_trans->sip_xaction_TE)
294 error = ENOMEM;
295 goto error_ret;
297 sip_trans->sip_xaction_state = SIP_CLNT_TRYING;
299 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
300 if (sip_xaction_ulp_state_cb != NULL) {
301 sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
302 (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
304 return (0);
306 error_ret:
307 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
308 if (timer_obj_A != NULL)
309 free(timer_obj_A);
310 if (timer_obj_B != NULL)
311 free(timer_obj_B);
312 if (timer_obj_E != NULL)
313 free(timer_obj_E);
314 if (timer_obj_F != NULL)
315 free(timer_obj_F);
316 return (error);
320 * Send a response out
322 static int
323 sip_srv_xaction_output(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
324 _sip_msg_t *msg)
326 int ret;
328 if (sip_trans->sip_xaction_method == INVITE)
329 ret = sip_srv_xaction_inv_res(conn_obj, sip_trans, msg);
330 else
331 ret = sip_srv_xaction_noninv_res(conn_obj, sip_trans, msg);
332 return (ret);
336 * Send a INVITE response out
338 static int
339 sip_srv_xaction_inv_res(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
340 _sip_msg_t *msg)
342 int resp_code;
343 sip_xaction_time_obj_t *timer_obj_G = NULL;
344 sip_xaction_time_obj_t *timer_obj_H = NULL;
345 sip_message_type_t *sip_msg_info = msg->sip_msg_req_res;
346 int prev_state;
347 boolean_t isreliable;
349 isreliable = sip_is_conn_reliable(conn_obj);
351 resp_code = sip_msg_info->sip_resp_code;
352 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
353 prev_state = sip_trans->sip_xaction_state;
354 switch (sip_trans->sip_xaction_state) {
355 case SIP_SRV_INV_PROCEEDING:
356 if (SIP_PROVISIONAL_RESP(resp_code)) {
357 if (sip_trans->sip_xaction_last_msg != NULL) {
358 SIP_MSG_REFCNT_DECR(
359 sip_trans->sip_xaction_last_msg);
360 sip_trans->sip_xaction_last_msg = NULL;
362 SIP_MSG_REFCNT_INCR(msg);
363 sip_trans->sip_xaction_last_msg = msg;
364 (void) sip_add_conn_obj_cache(conn_obj,
365 (void *)sip_trans);
366 } else if (SIP_OK_RESP(resp_code)) {
367 sip_trans->sip_xaction_state =
368 SIP_SRV_INV_TERMINATED;
369 } else if (SIP_NONOK_FINAL_RESP(resp_code)) {
370 if (sip_trans->sip_xaction_last_msg != NULL) {
371 SIP_MSG_REFCNT_DECR(
372 sip_trans->sip_xaction_last_msg);
373 sip_trans->sip_xaction_last_msg = NULL;
375 SIP_MSG_REFCNT_INCR(msg);
376 sip_trans->sip_xaction_last_msg = msg;
377 (void) sip_add_conn_obj_cache(conn_obj,
378 (void *)sip_trans);
380 * For unreliable transport start timer G
382 if (!isreliable) {
383 timer_obj_G = sip_setup_timer(
384 conn_obj, sip_trans,
385 NULL, sip_trans->sip_xaction_TG,
386 SIP_XACTION_TIMER_G);
387 if (timer_obj_G == NULL) {
388 (void) pthread_mutex_unlock(
389 &sip_trans->
390 sip_xaction_mutex);
391 return (ENOMEM);
395 * Start Timer H
397 timer_obj_H = sip_setup_timer(
398 conn_obj, sip_trans,
399 NULL, sip_trans->sip_xaction_TH,
400 SIP_XACTION_TIMER_H);
401 if (timer_obj_H == NULL) {
402 free(timer_obj_G);
403 (void) pthread_mutex_unlock(
404 &sip_trans->sip_xaction_mutex);
405 return (ENOMEM);
407 if (timer_obj_G != NULL) {
408 SIP_SCHED_TIMER(
409 sip_trans->sip_xaction_TG,
410 timer_obj_G,
411 sip_xaction_state_timer_fire);
412 if (!SIP_IS_TIMER_RUNNING(
413 sip_trans->sip_xaction_TG)) {
414 (void) pthread_mutex_unlock(
415 &sip_trans->
416 sip_xaction_mutex);
417 free(timer_obj_G);
418 return (ENOMEM);
421 if (timer_obj_H != NULL) {
422 SIP_SCHED_TIMER(
423 sip_trans->sip_xaction_TH,
424 timer_obj_H,
425 sip_xaction_state_timer_fire);
426 if (!SIP_IS_TIMER_RUNNING(
427 sip_trans->sip_xaction_TH)) {
428 if (timer_obj_G != NULL) {
429 SIP_CANCEL_TIMER(
430 sip_trans->
431 sip_xaction_TG);
432 free(timer_obj_G);
434 (void) pthread_mutex_unlock(
435 &sip_trans->
436 sip_xaction_mutex);
437 free(timer_obj_H);
438 return (ENOMEM);
441 sip_trans->sip_xaction_state =
442 SIP_SRV_INV_COMPLETED;
444 break;
445 default:
446 (void) pthread_mutex_unlock(
447 &sip_trans->sip_xaction_mutex);
448 return (EPROTO);
450 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
451 if (prev_state != sip_trans->sip_xaction_state &&
452 sip_xaction_ulp_state_cb != NULL) {
453 sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
454 (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
456 return (0);
460 * Send a NON-INVITE response out
462 static int
463 sip_srv_xaction_noninv_res(sip_conn_object_t conn_obj,
464 sip_xaction_t *sip_trans, _sip_msg_t *msg)
466 int resp_code;
467 sip_xaction_time_obj_t *timer_obj_J = NULL;
468 sip_message_type_t *sip_msg_info = msg->sip_msg_req_res;
469 int prev_state;
470 boolean_t isreliable;
472 resp_code = sip_msg_info->sip_resp_code;
473 isreliable = sip_is_conn_reliable(conn_obj);
475 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
476 prev_state = sip_trans->sip_xaction_state;
477 switch (sip_trans->sip_xaction_state) {
478 case SIP_SRV_TRYING:
479 if (sip_trans->sip_xaction_last_msg != NULL) {
480 SIP_MSG_REFCNT_DECR(
481 sip_trans->sip_xaction_last_msg);
482 sip_trans->sip_xaction_last_msg = NULL;
484 SIP_MSG_REFCNT_INCR(msg);
485 sip_trans->sip_xaction_last_msg = msg;
486 (void) sip_add_conn_obj_cache(conn_obj,
487 (void *)sip_trans);
488 if (SIP_PROVISIONAL_RESP(resp_code)) {
489 sip_trans->sip_xaction_state =
490 SIP_SRV_NONINV_PROCEEDING;
491 } else if (SIP_FINAL_RESP(resp_code)) {
493 * For unreliable transports, start Timer J
495 if (!isreliable) {
496 timer_obj_J = sip_setup_timer(
497 conn_obj, sip_trans,
498 NULL, sip_trans->sip_xaction_TJ,
499 SIP_XACTION_TIMER_J);
500 if (timer_obj_J == NULL) {
501 (void) pthread_mutex_unlock(&
502 sip_trans->
503 sip_xaction_mutex);
504 return (ENOMEM);
506 SIP_SCHED_TIMER(
507 sip_trans->sip_xaction_TJ,
508 timer_obj_J,
509 sip_xaction_state_timer_fire);
510 if (!SIP_IS_TIMER_RUNNING(
511 sip_trans->sip_xaction_TJ)) {
512 (void) pthread_mutex_unlock(&
513 sip_trans->
514 sip_xaction_mutex);
515 free(timer_obj_J);
516 return (ENOMEM);
518 sip_trans->sip_xaction_state =
519 SIP_SRV_NONINV_COMPLETED;
520 } else {
521 sip_trans->sip_xaction_state =
522 SIP_SRV_NONINV_TERMINATED;
525 break;
526 case SIP_SRV_NONINV_PROCEEDING:
527 if (sip_trans->sip_xaction_last_msg != NULL) {
528 SIP_MSG_REFCNT_DECR(
529 sip_trans->sip_xaction_last_msg);
530 sip_trans->sip_xaction_last_msg = NULL;
532 SIP_MSG_REFCNT_INCR(msg);
533 sip_trans->sip_xaction_last_msg = msg;
534 (void) sip_add_conn_obj_cache(conn_obj,
535 (void *)sip_trans);
536 if (SIP_PROVISIONAL_RESP(resp_code)) {
537 break;
538 } else if (SIP_FINAL_RESP(resp_code)) {
540 * For unreliable transports, start Timer J
542 if (!isreliable) {
543 timer_obj_J = sip_setup_timer(
544 conn_obj, sip_trans,
545 NULL, sip_trans->sip_xaction_TJ,
546 SIP_XACTION_TIMER_J);
547 if (timer_obj_J == NULL) {
548 (void) pthread_mutex_unlock(&
549 sip_trans->
550 sip_xaction_mutex);
551 return (ENOMEM);
553 SIP_SCHED_TIMER(
554 sip_trans->sip_xaction_TJ,
555 timer_obj_J,
556 sip_xaction_state_timer_fire);
557 if (!SIP_IS_TIMER_RUNNING(
558 sip_trans->sip_xaction_TJ)) {
559 (void) pthread_mutex_unlock(&
560 sip_trans->
561 sip_xaction_mutex);
562 free(timer_obj_J);
563 return (ENOMEM);
565 sip_trans->sip_xaction_state =
566 SIP_SRV_NONINV_COMPLETED;
567 } else {
568 sip_trans->sip_xaction_state =
569 SIP_SRV_NONINV_TERMINATED;
572 break;
573 default:
574 (void) pthread_mutex_unlock(
575 &sip_trans->sip_xaction_mutex);
576 return (EPROTO);
578 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
579 if (prev_state != sip_trans->sip_xaction_state &&
580 sip_xaction_ulp_state_cb != NULL) {
581 sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
582 (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
584 return (0);
589 * -------------------------- Input Routines ---------------------------
593 * Process an incoming SIP message Request or Response
596 sip_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
597 _sip_msg_t **sip_msg)
599 sip_message_type_t *sip_msg_info;
600 int ret;
602 sip_msg_info = (*sip_msg)->sip_msg_req_res;
604 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
605 sip_trans->sip_xaction_msgcnt++;
606 sip_add_log(&sip_trans->sip_xaction_log[sip_trans->sip_xaction_state],
607 (sip_msg_t)*sip_msg, sip_trans->sip_xaction_msgcnt,
608 SIP_TRANSACTION_LOG);
609 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
611 if (sip_msg_info->is_request)
612 ret = sip_srv_xaction_input(conn_obj, sip_trans, sip_msg);
613 else
614 ret = sip_clnt_xaction_input(conn_obj, sip_trans, sip_msg);
615 return (ret);
619 * Process a Request from the transport
621 static int
622 sip_srv_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
623 _sip_msg_t **sip_msg)
625 sip_message_type_t *sip_msg_info;
626 _sip_msg_t *msg = *sip_msg;
627 int prev_state;
628 boolean_t isreliable;
630 sip_msg_info = msg->sip_msg_req_res;
631 isreliable = sip_is_conn_reliable(conn_obj);
634 * Cancel if the original transaction has not yet got a final
635 * response and send a 487 response.
637 if (sip_msg_info->sip_req_method == ACK) {
638 _sip_msg_t *sip_last_resp;
639 const sip_str_t *resp_to_tag;
640 const sip_str_t *req_to_tag;
641 int error;
642 sip_message_type_t *last_msg_info;
644 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
646 if (sip_trans->sip_xaction_last_msg != NULL)
647 sip_last_resp = sip_trans->sip_xaction_last_msg;
648 else
649 sip_last_resp = sip_trans->sip_xaction_orig_msg;
650 last_msg_info = sip_last_resp->sip_msg_req_res;
651 if (last_msg_info->is_request) {
652 (void) pthread_mutex_unlock(
653 &sip_trans->sip_xaction_mutex);
654 return (0);
656 req_to_tag = sip_get_to_tag((sip_msg_t)msg, &error);
657 if (req_to_tag == NULL || error != 0) {
658 (void) pthread_mutex_unlock(
659 &sip_trans->sip_xaction_mutex);
660 return (0);
662 resp_to_tag = sip_get_to_tag((sip_msg_t)sip_last_resp,
663 &error);
664 if (req_to_tag == NULL || error != 0) {
665 (void) pthread_mutex_unlock(
666 &sip_trans->sip_xaction_mutex);
667 return (0);
669 if (resp_to_tag->sip_str_len != req_to_tag->sip_str_len ||
670 strncmp(resp_to_tag->sip_str_ptr, req_to_tag->sip_str_ptr,
671 req_to_tag->sip_str_len) != 0) {
672 (void) pthread_mutex_unlock(
673 &sip_trans->sip_xaction_mutex);
674 return (0);
676 prev_state = sip_trans->sip_xaction_state;
677 if (sip_trans->sip_xaction_state == SIP_SRV_INV_COMPLETED) {
678 sip_xaction_time_obj_t *timer_obj_I = NULL;
680 SIP_CANCEL_TIMER(sip_trans->sip_xaction_TG);
682 * Cancel Timer H and goto TERMINATED state for
683 * reliable transports.
685 if (isreliable) {
686 SIP_CANCEL_TIMER(
687 sip_trans->sip_xaction_TH);
688 sip_trans->sip_xaction_state =
689 SIP_SRV_INV_TERMINATED;
690 (void) pthread_mutex_unlock(
691 &sip_trans->sip_xaction_mutex);
692 if (sip_xaction_ulp_state_cb != NULL) {
693 sip_xaction_ulp_state_cb(
694 (sip_transaction_t)sip_trans,
695 (sip_msg_t)msg, prev_state,
696 sip_trans->sip_xaction_state);
698 return (0);
701 * For unreliable transports, start TIMER I and
702 * transition to CONFIRMED state.
704 timer_obj_I = sip_setup_timer(conn_obj, sip_trans,
705 NULL,
706 sip_trans->sip_xaction_TI, SIP_XACTION_TIMER_I);
707 if (timer_obj_I == NULL) {
708 (void) pthread_mutex_unlock(
709 &sip_trans->sip_xaction_mutex);
710 return (ENOMEM);
712 SIP_SCHED_TIMER(sip_trans->sip_xaction_TI,
713 timer_obj_I, sip_xaction_state_timer_fire);
714 if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TI)) {
715 (void) pthread_mutex_unlock(
716 &sip_trans->sip_xaction_mutex);
717 free(timer_obj_I);
718 return (ENOMEM);
720 sip_trans->sip_xaction_state = SIP_SRV_CONFIRMED;
722 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
723 if (prev_state != sip_trans->sip_xaction_state &&
724 sip_xaction_ulp_state_cb != NULL) {
725 sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
726 (sip_msg_t)msg, prev_state,
727 sip_trans->sip_xaction_state);
729 return (0);
730 } else if (sip_msg_info->sip_req_method == CANCEL) {
731 if (sip_trans->sip_xaction_method == INVITE) {
732 (void) pthread_mutex_unlock(
733 &sip_trans->sip_xaction_mutex);
734 return (0);
737 if (sip_msg_info->sip_req_method == INVITE) {
738 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
739 if (sip_trans->sip_xaction_method != INVITE) {
740 sip_write_to_log((void *)sip_trans,
741 SIP_TRANSACTION_LOG | SIP_ASSERT_ERROR, __FILE__,
742 __LINE__);
744 assert(sip_trans->sip_xaction_method == INVITE);
746 * Retransmitted invite
748 switch (sip_trans->sip_xaction_state) {
749 case SIP_SRV_INV_PROCEEDING:
750 case SIP_SRV_INV_COMPLETED:
751 if (sip_trans->sip_xaction_last_msg != NULL) {
752 _sip_msg_t *new_msg;
753 sip_message_type_t *msg_info;
754 int resp;
756 new_msg =
757 sip_trans->sip_xaction_last_msg;
758 msg_info = new_msg->sip_msg_req_res;
759 if (msg_info == NULL || msg_info->
760 is_request) {
761 sip_write_to_log((void *)
762 sip_trans,
763 SIP_TRANSACTION_LOG |
764 SIP_ASSERT_ERROR, __FILE__,
765 __LINE__);
767 assert(msg_info != NULL && !msg_info->
768 is_request);
769 resp = msg_info->sip_resp_code;
770 SIP_UPDATE_COUNTERS(B_FALSE, 0, resp,
771 B_TRUE, new_msg->sip_msg_len);
772 ++sip_trans->sip_xaction_msgcnt;
773 sip_add_log(&sip_trans->sip_xaction_log[
774 sip_trans->sip_xaction_state],
775 new_msg, sip_trans->
776 sip_xaction_msgcnt,
777 SIP_TRANSACTION_LOG);
778 (void) sip_stack_send(conn_obj,
779 new_msg->sip_msg_buf,
780 new_msg->sip_msg_len);
782 break;
783 default:
784 (void) pthread_mutex_unlock(
785 &sip_trans->sip_xaction_mutex);
786 return (EPROTO);
788 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
790 * We need to account for this invite received by the stack
791 * before we free that message.
793 SIP_UPDATE_COUNTERS(B_TRUE, INVITE, 0, B_FALSE,
794 msg->sip_msg_len);
795 sip_free_msg((sip_msg_t)msg);
796 *sip_msg = NULL;
797 return (0);
800 * Retransmitted request
802 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
803 if (sip_trans->sip_xaction_method == INVITE) {
804 sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
805 SIP_ASSERT_ERROR, __FILE__, __LINE__);
807 assert(sip_trans->sip_xaction_method != INVITE);
808 switch (sip_trans->sip_xaction_state) {
809 case SIP_SRV_NONINV_PROCEEDING:
810 case SIP_SRV_NONINV_COMPLETED:
811 if (sip_trans->sip_xaction_last_msg != NULL) {
812 _sip_msg_t *new_msg;
813 sip_message_type_t *msg_info;
814 int resp;
816 new_msg = sip_trans->sip_xaction_last_msg;
817 msg_info = new_msg->sip_msg_req_res;
818 if (msg_info == NULL || msg_info->is_request) {
819 sip_write_to_log((void *)sip_trans,
820 SIP_TRANSACTION_LOG |
821 SIP_ASSERT_ERROR, __FILE__,
822 __LINE__);
824 assert(msg_info != NULL && !msg_info->
825 is_request);
826 resp = msg_info->sip_resp_code;
827 SIP_UPDATE_COUNTERS(B_FALSE, 0, resp, B_TRUE,
828 new_msg->sip_msg_len);
829 ++sip_trans->sip_xaction_msgcnt;
830 sip_add_log(&sip_trans->sip_xaction_log[
831 sip_trans->sip_xaction_state], new_msg,
832 sip_trans->sip_xaction_msgcnt,
833 SIP_TRANSACTION_LOG);
834 (void) sip_stack_send(conn_obj,
835 new_msg->sip_msg_buf, new_msg->sip_msg_len);
837 break;
838 default:
839 (void) pthread_mutex_unlock(
840 &sip_trans->sip_xaction_mutex);
841 return (EPROTO);
843 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
845 * We need to account for the retransmitted non-INVITE request here.
846 * When we return from here the msg will be freed and we will not
847 * be able to capture the details at sip_process_new_packet()
849 SIP_UPDATE_COUNTERS(B_TRUE, sip_msg_info->sip_req_method, 0, B_FALSE,
850 msg->sip_msg_len);
851 sip_free_msg((sip_msg_t)msg);
852 *sip_msg = NULL;
853 return (0);
857 * Process a Response
859 static int
860 sip_clnt_xaction_input(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
861 _sip_msg_t **msg)
863 int ret;
865 if (sip_trans->sip_xaction_method == INVITE)
866 ret = sip_clnt_xaction_inv_res(conn_obj, sip_trans, msg);
867 else
868 ret = sip_clnt_xaction_noninv_res(conn_obj, sip_trans, msg);
870 return (ret);
873 static int
874 sip_create_send_nonOKack(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
875 _sip_msg_t *msg, boolean_t copy)
877 _sip_msg_t *ack_msg;
878 int ret = 0;
880 ack_msg = (_sip_msg_t *)sip_new_msg();
881 if (ack_msg == NULL)
882 return (ENOMEM);
883 if ((ret = sip_create_nonOKack(
884 (sip_msg_t)sip_trans->sip_xaction_orig_msg, (sip_msg_t)msg,
885 (sip_msg_t)ack_msg)) != 0) {
886 sip_free_msg((sip_msg_t)ack_msg);
887 return (ret);
889 SIP_UPDATE_COUNTERS(B_TRUE, ACK, 0, B_TRUE, ack_msg->sip_msg_len);
890 ++sip_trans->sip_xaction_msgcnt;
891 sip_add_log(&sip_trans->sip_xaction_log[sip_trans->sip_xaction_state],
892 ack_msg, sip_trans->sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
893 if ((ret = sip_stack_send(conn_obj, ack_msg->sip_msg_buf,
894 ack_msg->sip_msg_len)) != 0) {
895 sip_free_msg((sip_msg_t)ack_msg);
896 return (ret);
898 if (copy) {
899 SIP_MSG_REFCNT_INCR(ack_msg);
900 if (sip_trans->sip_xaction_last_msg != NULL) {
901 SIP_MSG_REFCNT_DECR(sip_trans->sip_xaction_last_msg);
902 sip_trans->sip_xaction_last_msg = NULL;
904 sip_trans->sip_xaction_last_msg = ack_msg;
906 sip_free_msg((sip_msg_t)ack_msg);
907 return (0);
911 * Process a INVITE Response
913 static int
914 sip_clnt_xaction_inv_res(sip_conn_object_t conn_obj, sip_xaction_t *sip_trans,
915 _sip_msg_t **sip_msg)
917 int resp_code;
918 _sip_msg_t *msg = *sip_msg;
919 sip_xaction_time_obj_t *timer_obj_D = NULL;
920 sip_message_type_t *sip_msg_info;
921 int prev_state;
922 boolean_t isreliable;
924 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
925 if (msg->sip_msg_req_res == NULL) {
926 sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
927 SIP_ASSERT_ERROR, __FILE__, __LINE__);
929 assert(msg->sip_msg_req_res != NULL);
931 sip_msg_info = msg->sip_msg_req_res;
932 resp_code = sip_msg_info->sip_resp_code;
933 isreliable = sip_is_conn_reliable(conn_obj);
935 prev_state = sip_trans->sip_xaction_state;
936 switch (sip_trans->sip_xaction_state) {
937 case SIP_CLNT_CALLING:
938 if (SIP_PROVISIONAL_RESP(resp_code)) {
940 * sip_trans->sip_xaction_last_msg ?
942 SIP_CANCEL_TIMER(
943 sip_trans->sip_xaction_TA);
944 sip_trans->sip_xaction_state =
945 SIP_CLNT_INV_PROCEEDING;
946 } else if (SIP_OK_RESP(resp_code)) {
948 * sip_trans->sip_xaction_last_msg ?
950 SIP_CANCEL_TIMER(
951 sip_trans->sip_xaction_TA);
952 SIP_CANCEL_TIMER(
953 sip_trans->sip_xaction_TB);
954 sip_trans->sip_xaction_state =
955 SIP_CLNT_INV_TERMINATED;
956 } else if (SIP_NONOK_FINAL_RESP(resp_code)) {
957 int ret;
960 * sip_trans->sip_xaction_last_msg ?
962 SIP_CANCEL_TIMER(
963 sip_trans->sip_xaction_TA);
964 SIP_CANCEL_TIMER(
965 sip_trans->sip_xaction_TB);
966 if ((ret = sip_create_send_nonOKack(conn_obj,
967 sip_trans, msg, B_FALSE)) != 0) {
968 (void) pthread_mutex_unlock(
969 &sip_trans->sip_xaction_mutex);
970 return (ret);
973 * start timer D for unreliable transports
975 if (!isreliable) {
976 timer_obj_D = sip_setup_timer(
977 conn_obj, sip_trans,
978 NULL, sip_trans->sip_xaction_TD,
979 SIP_XACTION_TIMER_D);
980 if (timer_obj_D == NULL) {
981 (void) pthread_mutex_unlock(
982 &sip_trans->
983 sip_xaction_mutex);
984 return (ENOMEM);
986 SIP_SCHED_TIMER(
987 sip_trans->sip_xaction_TD,
988 timer_obj_D,
989 sip_xaction_state_timer_fire);
990 if (!SIP_IS_TIMER_RUNNING(
991 sip_trans->sip_xaction_TD)) {
992 (void) pthread_mutex_unlock(
993 &sip_trans->
994 sip_xaction_mutex);
995 free(timer_obj_D);
996 return (ENOMEM);
998 sip_trans->sip_xaction_state =
999 SIP_CLNT_INV_COMPLETED;
1000 } else {
1001 sip_trans->sip_xaction_state =
1002 SIP_CLNT_INV_TERMINATED;
1004 } else {
1006 * Invalid resp_code
1008 (void) pthread_mutex_unlock(
1009 &sip_trans->sip_xaction_mutex);
1010 return (EPROTO);
1012 break;
1013 case SIP_CLNT_INV_PROCEEDING:
1014 if (SIP_PROVISIONAL_RESP(resp_code)) {
1015 break;
1016 } else if (SIP_OK_RESP(resp_code)) {
1017 SIP_CANCEL_TIMER(
1018 sip_trans->sip_xaction_TB);
1019 sip_trans->sip_xaction_state =
1020 SIP_CLNT_INV_TERMINATED;
1021 } else if (SIP_NONOK_FINAL_RESP(resp_code)) {
1022 int ret;
1024 SIP_CANCEL_TIMER(
1025 sip_trans->sip_xaction_TB);
1026 if ((ret = sip_create_send_nonOKack(conn_obj,
1027 sip_trans, msg, B_FALSE)) != 0) {
1028 (void) pthread_mutex_unlock(
1029 &sip_trans->sip_xaction_mutex);
1030 return (ret);
1033 * start timer D for unreliable transports
1035 if (!isreliable) {
1036 timer_obj_D = sip_setup_timer(
1037 conn_obj, sip_trans,
1038 NULL, sip_trans->sip_xaction_TD,
1039 SIP_XACTION_TIMER_D);
1040 if (timer_obj_D == NULL) {
1041 (void) pthread_mutex_unlock(
1042 &sip_trans->
1043 sip_xaction_mutex);
1044 return (ENOMEM);
1046 SIP_SCHED_TIMER(
1047 sip_trans->sip_xaction_TD,
1048 timer_obj_D,
1049 sip_xaction_state_timer_fire);
1050 if (!SIP_IS_TIMER_RUNNING(
1051 sip_trans->sip_xaction_TD)) {
1052 (void) pthread_mutex_unlock(
1053 &sip_trans->
1054 sip_xaction_mutex);
1055 free(timer_obj_D);
1056 return (ENOMEM);
1058 sip_trans->sip_xaction_state =
1059 SIP_CLNT_INV_COMPLETED;
1060 } else {
1061 sip_trans->sip_xaction_state =
1062 SIP_CLNT_INV_TERMINATED;
1064 } else {
1065 (void) pthread_mutex_unlock(
1066 &sip_trans->sip_xaction_mutex);
1067 return (EPROTO);
1069 break;
1070 case SIP_CLNT_INV_COMPLETED:
1072 * Transport error takes it to
1073 * SIP_CLNT_INV_TERMINATED
1075 if (SIP_NONOK_FINAL_RESP(resp_code)) {
1076 int ret;
1078 if ((ret = sip_create_send_nonOKack(conn_obj,
1079 sip_trans, msg, B_FALSE)) != 0) {
1080 (void) pthread_mutex_unlock(
1081 &sip_trans->sip_xaction_mutex);
1082 return (ret);
1084 } else {
1086 * Invalid resp_code
1088 (void) pthread_mutex_unlock(
1089 &sip_trans->sip_xaction_mutex);
1090 return (EPROTO);
1092 break;
1093 default:
1094 (void) pthread_mutex_unlock(
1095 &sip_trans->sip_xaction_mutex);
1096 return (EPROTO);
1098 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
1099 if (prev_state != sip_trans->sip_xaction_state &&
1100 sip_xaction_ulp_state_cb != NULL) {
1101 sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
1102 (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
1104 return (0);
1108 * Process a NON-INVITE Response
1110 static int
1111 sip_clnt_xaction_noninv_res(sip_conn_object_t conn_obj,
1112 sip_xaction_t *sip_trans, _sip_msg_t **sip_msg)
1114 int resp_code;
1115 sip_xaction_time_obj_t *timer_obj_K = NULL;
1116 sip_message_type_t *sip_msg_info;
1117 int prev_state;
1118 _sip_msg_t *msg = *sip_msg;
1119 boolean_t isreliable;
1121 if (msg->sip_msg_req_res == NULL || sip_trans == NULL) {
1122 sip_write_to_log((void *)sip_trans, SIP_TRANSACTION_LOG |
1123 SIP_ASSERT_ERROR, __FILE__, __LINE__);
1125 assert(msg->sip_msg_req_res != NULL);
1126 assert(sip_trans != NULL);
1128 sip_msg_info = msg->sip_msg_req_res;
1129 isreliable = sip_is_conn_reliable(conn_obj);
1130 resp_code = sip_msg_info->sip_resp_code;
1131 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
1132 prev_state = sip_trans->sip_xaction_state;
1133 switch (sip_trans->sip_xaction_state) {
1134 case SIP_CLNT_TRYING:
1135 if (SIP_PROVISIONAL_RESP(resp_code)) {
1136 sip_trans->sip_xaction_state =
1137 SIP_CLNT_NONINV_PROCEEDING;
1138 } else if (SIP_FINAL_RESP(resp_code)) {
1139 SIP_CANCEL_TIMER(
1140 sip_trans->sip_xaction_TE);
1141 SIP_CANCEL_TIMER(
1142 sip_trans->sip_xaction_TF);
1144 * Start timer K for unreliable transports
1146 if (!isreliable) {
1147 timer_obj_K = sip_setup_timer(
1148 conn_obj, sip_trans,
1149 NULL, sip_trans->sip_xaction_TK,
1150 SIP_XACTION_TIMER_K);
1151 if (timer_obj_K == NULL) {
1152 (void) pthread_mutex_unlock(&
1153 sip_trans->
1154 sip_xaction_mutex);
1155 return (ENOMEM);
1157 SIP_SCHED_TIMER(
1158 sip_trans->sip_xaction_TK,
1159 timer_obj_K,
1160 sip_xaction_state_timer_fire);
1161 if (!SIP_IS_TIMER_RUNNING(
1162 sip_trans->sip_xaction_TK)) {
1163 (void) pthread_mutex_unlock(
1164 &sip_trans->
1165 sip_xaction_mutex);
1166 free(timer_obj_K);
1167 return (ENOMEM);
1169 sip_trans->sip_xaction_state =
1170 SIP_CLNT_NONINV_COMPLETED;
1171 } else {
1172 sip_trans->sip_xaction_state =
1173 SIP_CLNT_NONINV_TERMINATED;
1176 break;
1177 case SIP_CLNT_NONINV_PROCEEDING:
1178 if (SIP_PROVISIONAL_RESP(resp_code)) {
1179 break;
1180 } else if (SIP_FINAL_RESP(resp_code)) {
1181 SIP_CANCEL_TIMER(
1182 sip_trans->sip_xaction_TE);
1183 SIP_CANCEL_TIMER(
1184 sip_trans->sip_xaction_TF);
1186 * Start timer K for unreliable transports
1188 if (!isreliable) {
1189 timer_obj_K = sip_setup_timer(
1190 conn_obj, sip_trans,
1191 NULL, sip_trans->sip_xaction_TK,
1192 SIP_XACTION_TIMER_K);
1193 if (timer_obj_K == NULL) {
1194 (void) pthread_mutex_unlock(&
1195 sip_trans->
1196 sip_xaction_mutex);
1197 return (ENOMEM);
1199 SIP_SCHED_TIMER(
1200 sip_trans->sip_xaction_TK,
1201 timer_obj_K,
1202 sip_xaction_state_timer_fire);
1203 if (!SIP_IS_TIMER_RUNNING(
1204 sip_trans->sip_xaction_TK)) {
1205 (void) pthread_mutex_unlock(
1206 &sip_trans->
1207 sip_xaction_mutex);
1208 free(timer_obj_K);
1209 return (ENOMEM);
1211 sip_trans->sip_xaction_state =
1212 SIP_CLNT_NONINV_COMPLETED;
1213 } else {
1214 sip_trans->sip_xaction_state =
1215 SIP_CLNT_NONINV_TERMINATED;
1218 break;
1219 default:
1220 (void) pthread_mutex_unlock(
1221 &sip_trans->sip_xaction_mutex);
1222 return (EPROTO);
1224 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
1225 if (prev_state != sip_trans->sip_xaction_state &&
1226 sip_xaction_ulp_state_cb != NULL) {
1227 sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
1228 (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
1230 return (0);
1234 * If there is a transport error, sending the message out, terminate the
1235 * transaction.
1237 /* ARGSUSED */
1238 void
1239 sip_xaction_terminate(sip_xaction_t *sip_trans, _sip_msg_t *msg, int transport)
1241 sip_message_type_t *sip_msg_info;
1242 int state;
1243 int prev_state;
1245 sip_msg_info = msg->sip_msg_req_res;
1246 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
1247 if (sip_msg_info->is_request) {
1248 if (sip_trans->sip_xaction_method == INVITE)
1249 state = SIP_CLNT_INV_TERMINATED;
1250 else
1251 state = SIP_CLNT_NONINV_TERMINATED;
1252 } else {
1253 if (sip_trans->sip_xaction_method == INVITE)
1254 state = SIP_SRV_INV_TERMINATED;
1255 else
1256 state = SIP_SRV_NONINV_TERMINATED;
1258 prev_state = sip_trans->sip_xaction_state;
1259 sip_trans->sip_xaction_state = state;
1260 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
1261 if (sip_xaction_ulp_state_cb != NULL) {
1262 sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
1263 (sip_msg_t)msg, prev_state, sip_trans->sip_xaction_state);
1265 sip_xaction_delete(sip_trans);
1269 * --------------------------- Timer Routine ---------------------------
1272 void
1273 sip_xaction_state_timer_fire(void *args)
1275 sip_xaction_time_obj_t *time_obj = (sip_xaction_time_obj_t *)args;
1276 sip_xaction_t *sip_trans = time_obj->sip_trans;
1277 _sip_msg_t *new_msg;
1278 boolean_t destroy_trans = B_FALSE;
1279 sip_conn_object_t conn_obj;
1280 int prev_state;
1281 sip_message_type_t *msg_info;
1282 int resp;
1283 sip_method_t method;
1285 assert(time_obj != NULL);
1287 (void) pthread_mutex_lock(&sip_trans->sip_xaction_mutex);
1288 prev_state = sip_trans->sip_xaction_state;
1289 switch (time_obj->sip_xaction_timer_type) {
1290 case SIP_XACTION_TIMER_A:
1291 if (sip_trans->sip_xaction_state != SIP_CLNT_CALLING)
1292 break;
1294 * Assert candidate
1296 if (sip_trans->sip_xaction_last_msg == NULL)
1297 break;
1298 if (sip_trans->sip_xaction_conn_obj == NULL)
1299 break;
1300 new_msg = sip_trans->sip_xaction_last_msg;
1301 conn_obj = sip_trans->sip_xaction_conn_obj;
1302 /* timer A is for INVITE-RETRANSMIT only */
1303 SIP_UPDATE_COUNTERS(B_TRUE, INVITE, 0, B_TRUE, new_msg->
1304 sip_msg_len);
1305 ++sip_trans->sip_xaction_msgcnt;
1306 sip_add_log(&sip_trans->sip_xaction_log[sip_trans->
1307 sip_xaction_state], new_msg, sip_trans->
1308 sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
1309 if (sip_stack_send(conn_obj, new_msg->sip_msg_buf,
1310 new_msg->sip_msg_len) != 0) {
1311 sip_del_conn_obj_cache(
1312 sip_trans->sip_xaction_conn_obj,
1313 (void *)sip_trans);
1314 sip_trans->sip_xaction_state =
1315 SIP_CLNT_INV_TERMINATED;
1316 (void) pthread_mutex_unlock(
1317 &sip_trans->sip_xaction_mutex);
1318 if (sip_xaction_ulp_state_cb != NULL) {
1319 sip_xaction_ulp_state_cb(
1320 (sip_transaction_t)sip_trans, NULL,
1321 prev_state, sip_trans->
1322 sip_xaction_state);
1324 if (sip_xaction_ulp_trans_err != NULL) {
1325 sip_xaction_ulp_trans_err(sip_trans, 0,
1326 NULL);
1328 sip_xaction_delete(sip_trans);
1329 free(time_obj);
1330 return;
1332 SIP_SET_TIMEOUT(sip_trans->sip_xaction_TA,
1333 2 * SIP_GET_TIMEOUT(sip_trans->sip_xaction_TA));
1335 * Reschedule the timer
1337 SIP_SCHED_TIMER(sip_trans->sip_xaction_TA,
1338 time_obj, sip_xaction_state_timer_fire);
1339 if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TA)) {
1340 sip_del_conn_obj_cache(
1341 sip_trans->sip_xaction_conn_obj,
1342 (void *)sip_trans);
1343 sip_trans->sip_xaction_state =
1344 SIP_CLNT_INV_TERMINATED;
1345 (void) pthread_mutex_unlock(
1346 &sip_trans->sip_xaction_mutex);
1347 if (sip_xaction_ulp_state_cb != NULL) {
1348 sip_xaction_ulp_state_cb(
1349 (sip_transaction_t)sip_trans, NULL,
1350 prev_state, sip_trans->
1351 sip_xaction_state);
1353 if (sip_xaction_ulp_trans_err != NULL) {
1354 sip_xaction_ulp_trans_err(sip_trans, 0,
1355 NULL);
1357 sip_xaction_delete(sip_trans);
1358 free(time_obj);
1359 return;
1361 (void) pthread_mutex_unlock(
1362 &sip_trans->sip_xaction_mutex);
1363 return;
1364 case SIP_XACTION_TIMER_B:
1365 SIP_CANCEL_TIMER(sip_trans->sip_xaction_TA);
1366 if (sip_trans->sip_xaction_state == SIP_CLNT_CALLING) {
1367 sip_trans->sip_xaction_state =
1368 SIP_CLNT_INV_TERMINATED;
1369 (void) pthread_mutex_unlock(
1370 &sip_trans->sip_xaction_mutex);
1371 if (sip_xaction_ulp_state_cb != NULL) {
1372 sip_xaction_ulp_state_cb(
1373 (sip_transaction_t)sip_trans, NULL,
1374 prev_state, sip_trans->
1375 sip_xaction_state);
1377 if (sip_xaction_ulp_trans_err != NULL) {
1378 sip_xaction_ulp_trans_err(sip_trans, 0,
1379 NULL);
1381 sip_xaction_delete(sip_trans);
1382 free(time_obj);
1383 return;
1385 break;
1386 case SIP_XACTION_TIMER_D:
1387 if (sip_trans->sip_xaction_state ==
1388 SIP_CLNT_INV_COMPLETED) {
1389 SIP_CANCEL_TIMER(
1390 sip_trans->sip_xaction_TB);
1391 sip_trans->sip_xaction_state =
1392 SIP_CLNT_INV_TERMINATED;
1393 destroy_trans = B_TRUE;
1395 break;
1396 case SIP_XACTION_TIMER_E:
1398 * Assert candidate
1400 if (sip_trans->sip_xaction_state != SIP_CLNT_TRYING &&
1401 sip_trans->sip_xaction_state !=
1402 SIP_CLNT_NONINV_PROCEEDING) {
1403 break;
1406 * Assert candidate
1408 if (sip_trans->sip_xaction_last_msg == NULL)
1409 break;
1410 if (sip_trans->sip_xaction_conn_obj == NULL)
1411 break;
1412 conn_obj = sip_trans->sip_xaction_conn_obj;
1413 new_msg = sip_trans->sip_xaction_last_msg;
1414 /* Timer E is for non-INVITE request */
1416 msg_info = new_msg->sip_msg_req_res;
1417 if (msg_info == NULL || !msg_info->is_request) {
1418 (void) sip_write_to_log((void *) sip_trans,
1419 SIP_TRANSACTION_LOG | SIP_ASSERT_ERROR,
1420 __FILE__, __LINE__);
1422 assert(msg_info != NULL && msg_info->is_request);
1423 method = msg_info->sip_req_method;
1424 SIP_UPDATE_COUNTERS(B_TRUE, method, 0, B_TRUE, new_msg->
1425 sip_msg_len);
1426 ++sip_trans->sip_xaction_msgcnt;
1427 sip_add_log(&sip_trans->sip_xaction_log[sip_trans->
1428 sip_xaction_state], new_msg, sip_trans->
1429 sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
1430 if (sip_stack_send(conn_obj, new_msg->sip_msg_buf,
1431 new_msg->sip_msg_len) != 0) {
1432 sip_del_conn_obj_cache(
1433 sip_trans->sip_xaction_conn_obj,
1434 (void *)sip_trans);
1435 sip_trans->sip_xaction_state =
1436 SIP_CLNT_NONINV_TERMINATED;
1437 (void) pthread_mutex_unlock(
1438 &sip_trans->sip_xaction_mutex);
1439 if (sip_xaction_ulp_state_cb != NULL) {
1440 sip_xaction_ulp_state_cb(
1441 (sip_transaction_t)sip_trans, NULL,
1442 prev_state, sip_trans->
1443 sip_xaction_state);
1445 if (sip_xaction_ulp_trans_err != NULL) {
1446 sip_xaction_ulp_trans_err(sip_trans, 0,
1447 NULL);
1449 sip_xaction_delete(sip_trans);
1450 free(time_obj);
1451 return;
1453 SIP_SET_TIMEOUT(sip_trans->sip_xaction_TE,
1454 MIN(SIP_TIMER_T2,
1455 2 * SIP_GET_TIMEOUT(sip_trans->sip_xaction_TE)));
1457 * Reschedule the timer
1459 SIP_SCHED_TIMER(sip_trans->sip_xaction_TE,
1460 time_obj, sip_xaction_state_timer_fire);
1461 if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TE)) {
1462 sip_del_conn_obj_cache(
1463 sip_trans->sip_xaction_conn_obj,
1464 (void *)sip_trans);
1465 sip_trans->sip_xaction_state =
1466 SIP_CLNT_NONINV_TERMINATED;
1467 (void) pthread_mutex_unlock(
1468 &sip_trans->sip_xaction_mutex);
1469 if (sip_xaction_ulp_state_cb != NULL) {
1470 sip_xaction_ulp_state_cb(
1471 (sip_transaction_t)sip_trans, NULL,
1472 prev_state, sip_trans->
1473 sip_xaction_state);
1475 if (sip_xaction_ulp_trans_err != NULL) {
1476 sip_xaction_ulp_trans_err(sip_trans, 0,
1477 NULL);
1479 sip_xaction_delete(sip_trans);
1480 free(time_obj);
1481 return;
1483 (void) pthread_mutex_unlock(
1484 &sip_trans->sip_xaction_mutex);
1485 return;
1486 case SIP_XACTION_TIMER_F:
1487 SIP_CANCEL_TIMER(sip_trans->sip_xaction_TE);
1488 if (sip_trans->sip_xaction_state == SIP_CLNT_TRYING ||
1489 sip_trans->sip_xaction_state ==
1490 SIP_CLNT_NONINV_PROCEEDING) {
1491 sip_trans->sip_xaction_state =
1492 SIP_CLNT_NONINV_TERMINATED;
1493 (void) pthread_mutex_unlock(
1494 &sip_trans->sip_xaction_mutex);
1495 if (sip_xaction_ulp_state_cb != NULL) {
1496 sip_xaction_ulp_state_cb(
1497 (sip_transaction_t)sip_trans, NULL,
1498 prev_state, sip_trans->
1499 sip_xaction_state);
1501 if (sip_xaction_ulp_trans_err != NULL) {
1502 sip_xaction_ulp_trans_err(sip_trans, 0,
1503 NULL);
1505 sip_xaction_delete(sip_trans);
1506 free(time_obj);
1507 return;
1509 break;
1510 case SIP_XACTION_TIMER_G:
1512 * Assert candidate
1514 if (sip_trans->sip_xaction_last_msg == NULL)
1515 break;
1516 if (sip_trans->sip_xaction_conn_obj == NULL)
1517 break;
1518 if (sip_trans->sip_xaction_state !=
1519 SIP_SRV_INV_COMPLETED) {
1520 break;
1522 new_msg = sip_trans->sip_xaction_last_msg;
1523 conn_obj = sip_trans->sip_xaction_conn_obj;
1524 msg_info = new_msg->sip_msg_req_res;
1525 if (msg_info == NULL || msg_info->is_request) {
1526 (void) sip_write_to_log((void *) sip_trans,
1527 SIP_TRANSACTION_LOG | SIP_ASSERT_ERROR,
1528 __FILE__, __LINE__);
1530 assert(msg_info != NULL && !msg_info->is_request);
1531 resp = msg_info->sip_resp_code;
1532 SIP_UPDATE_COUNTERS(B_FALSE, 0, resp, B_TRUE, new_msg->
1533 sip_msg_len);
1534 ++sip_trans->sip_xaction_msgcnt;
1535 sip_add_log(&sip_trans->sip_xaction_log[sip_trans->
1536 sip_xaction_state], new_msg, sip_trans->
1537 sip_xaction_msgcnt, SIP_TRANSACTION_LOG);
1538 if (sip_stack_send(conn_obj, new_msg->sip_msg_buf,
1539 new_msg->sip_msg_len) != 0) {
1540 sip_del_conn_obj_cache(
1541 sip_trans->sip_xaction_conn_obj,
1542 (void *)sip_trans);
1543 sip_trans->sip_xaction_state =
1544 SIP_SRV_INV_TERMINATED;
1545 (void) pthread_mutex_unlock(
1546 &sip_trans->sip_xaction_mutex);
1547 if (sip_xaction_ulp_state_cb != NULL) {
1548 sip_xaction_ulp_state_cb(
1549 (sip_transaction_t)sip_trans, NULL,
1550 prev_state, sip_trans->
1551 sip_xaction_state);
1553 if (sip_xaction_ulp_trans_err != NULL) {
1554 sip_xaction_ulp_trans_err(sip_trans, 0,
1555 NULL);
1557 sip_xaction_delete(sip_trans);
1558 free(time_obj);
1559 return;
1561 SIP_SET_TIMEOUT(sip_trans->sip_xaction_TG,
1562 MIN(SIP_TIMER_T2,
1563 2 * SIP_GET_TIMEOUT(sip_trans->sip_xaction_TG)));
1564 SIP_SCHED_TIMER(sip_trans->sip_xaction_TG,
1565 time_obj, sip_xaction_state_timer_fire);
1566 if (!SIP_IS_TIMER_RUNNING(sip_trans->sip_xaction_TG)) {
1567 sip_del_conn_obj_cache(
1568 sip_trans->sip_xaction_conn_obj,
1569 (void *)sip_trans);
1570 sip_trans->sip_xaction_state =
1571 SIP_SRV_INV_TERMINATED;
1572 (void) pthread_mutex_unlock(
1573 &sip_trans->sip_xaction_mutex);
1574 if (sip_xaction_ulp_state_cb != NULL) {
1575 sip_xaction_ulp_state_cb(
1576 (sip_transaction_t)sip_trans, NULL,
1577 prev_state, sip_trans->
1578 sip_xaction_state);
1580 if (sip_xaction_ulp_trans_err != NULL) {
1581 sip_xaction_ulp_trans_err(sip_trans, 0,
1582 NULL);
1584 sip_xaction_delete(sip_trans);
1585 free(time_obj);
1586 return;
1588 (void) pthread_mutex_unlock(
1589 &sip_trans->sip_xaction_mutex);
1590 return;
1591 case SIP_XACTION_TIMER_H:
1592 SIP_CANCEL_TIMER(sip_trans->sip_xaction_TG);
1593 if (sip_trans->sip_xaction_state ==
1594 SIP_SRV_INV_COMPLETED) {
1595 sip_trans->sip_xaction_state =
1596 SIP_SRV_INV_TERMINATED;
1597 (void) pthread_mutex_unlock(
1598 &sip_trans->sip_xaction_mutex);
1599 if (sip_xaction_ulp_state_cb != NULL) {
1600 sip_xaction_ulp_state_cb(
1601 (sip_transaction_t)sip_trans, NULL,
1602 prev_state, sip_trans->
1603 sip_xaction_state);
1605 if (sip_xaction_ulp_trans_err != NULL) {
1606 sip_xaction_ulp_trans_err(sip_trans, 0,
1607 NULL);
1609 sip_xaction_delete(sip_trans);
1610 free(time_obj);
1611 return;
1613 break;
1614 case SIP_XACTION_TIMER_I:
1615 if (sip_trans->sip_xaction_state ==
1616 SIP_SRV_CONFIRMED) {
1617 SIP_CANCEL_TIMER(
1618 sip_trans->sip_xaction_TH);
1619 sip_trans->sip_xaction_state =
1620 SIP_SRV_INV_TERMINATED;
1621 destroy_trans = B_TRUE;
1623 break;
1624 case SIP_XACTION_TIMER_J:
1625 if (sip_trans->sip_xaction_state ==
1626 SIP_SRV_NONINV_COMPLETED) {
1627 sip_trans->sip_xaction_state =
1628 SIP_SRV_NONINV_TERMINATED;
1629 destroy_trans = B_TRUE;
1632 break;
1633 case SIP_XACTION_TIMER_K:
1634 if (sip_trans->sip_xaction_state ==
1635 SIP_CLNT_NONINV_COMPLETED) {
1636 SIP_CANCEL_TIMER(
1637 sip_trans->sip_xaction_TF);
1638 sip_trans->sip_xaction_state =
1639 SIP_CLNT_NONINV_TERMINATED;
1640 destroy_trans = B_TRUE;
1642 break;
1643 default:
1644 break;
1646 if (destroy_trans) {
1647 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
1648 if (sip_xaction_ulp_state_cb != NULL &&
1649 prev_state != sip_trans->sip_xaction_state) {
1650 sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans,
1651 NULL, prev_state, sip_trans->sip_xaction_state);
1653 sip_xaction_delete(sip_trans);
1654 free(time_obj);
1655 return;
1657 (void) pthread_mutex_unlock(&sip_trans->sip_xaction_mutex);
1658 if (sip_xaction_ulp_state_cb != NULL &&
1659 prev_state != sip_trans->sip_xaction_state) {
1660 sip_xaction_ulp_state_cb((sip_transaction_t)sip_trans, NULL,
1661 prev_state, sip_trans->sip_xaction_state);
1663 free(time_obj);