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]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
33 #include "sip_parse_uri.h"
35 #include "sip_miscdefs.h"
36 #include "sip_xaction.h"
39 #define RFC_3261_BRANCH "z9hG4bK"
42 * The transaction hash table
44 sip_hash_t sip_xaction_hash
[SIP_HASH_SZ
];
46 int (*sip_xaction_ulp_trans_err
)(sip_transaction_t
, int, void *) = NULL
;
47 void (*sip_xaction_ulp_state_cb
)(sip_transaction_t
, sip_msg_t
, int, int) = NULL
;
49 int sip_xaction_add(sip_xaction_t
*, char *, _sip_msg_t
*, sip_method_t
);
50 static boolean_t
sip_is_conn_obj_cache(sip_conn_object_t
, void *);
53 * Get the md5 hash of the required fields
56 sip_find_md5_digest(char *bid
, _sip_msg_t
*msg
, uint16_t *hindex
,
61 is_2543
= (bid
== NULL
||
62 strncmp(bid
, RFC_3261_BRANCH
, strlen(RFC_3261_BRANCH
)) != 0);
64 if (is_2543
&& msg
== NULL
)
67 _sip_header_t
*from
= NULL
;
68 _sip_header_t
*cid
= NULL
;
69 _sip_header_t
*via
= NULL
;
70 const sip_str_t
*to_uri
= NULL
;
75 * Since the response might contain parameters not in the
76 * request, just use the to URI.
78 to_uri
= sip_get_to_uri_str((sip_msg_t
)msg
, &error
);
79 if (to_uri
== NULL
|| error
!= 0)
81 cseq
= sip_get_callseq_num((sip_msg_t
)msg
, &error
);
82 if (cseq
< 0 || error
!= 0)
84 (void) pthread_mutex_lock(&msg
->sip_msg_mutex
);
85 via
= sip_search_for_header(msg
, SIP_VIA
, NULL
);
86 from
= sip_search_for_header(msg
, SIP_FROM
, NULL
);
87 cid
= sip_search_for_header(msg
, SIP_CALL_ID
, NULL
);
88 (void) pthread_mutex_unlock(&msg
->sip_msg_mutex
);
89 if (via
== NULL
|| from
== NULL
|| cid
== NULL
)
91 sip_md5_hash(via
->sip_hdr_start
,
92 via
->sip_hdr_end
- via
->sip_hdr_start
,
94 cid
->sip_hdr_end
- cid
->sip_hdr_start
,
96 from
->sip_hdr_end
- from
->sip_hdr_start
,
97 (char *)&cseq
, sizeof (int),
98 (char *)&method
, sizeof (sip_method_t
),
99 to_uri
->sip_str_ptr
, to_uri
->sip_str_len
,
102 sip_md5_hash(bid
, strlen(bid
), (char *)&method
,
103 sizeof (sip_method_t
), NULL
, 0, NULL
, 0, NULL
, 0, NULL
, 0,
110 * Add object to the connection cache object. Not checking for duplicates!!
113 sip_add_conn_obj_cache(sip_conn_object_t obj
, void *cobj
)
116 sip_conn_obj_pvt_t
*pvt_data
;
117 sip_conn_cache_t
*xaction_list
;
118 sip_xaction_t
*sip_trans
= (sip_xaction_t
*)cobj
;
123 if (sip_trans
->sip_xaction_conn_obj
!= NULL
) {
124 if (sip_is_conn_obj_cache(sip_trans
->sip_xaction_conn_obj
,
125 (void *)sip_trans
)) {
129 * Transaction has cached a different conn_obj, release it
131 sip_del_conn_obj_cache(sip_trans
->sip_xaction_conn_obj
,
135 xaction_list
= malloc(sizeof (sip_conn_cache_t
));
136 if (xaction_list
== NULL
)
138 xaction_list
->obj
= cobj
;
139 xaction_list
->next
= xaction_list
->prev
= NULL
;
141 obj_val
= (void *)obj
;
142 pvt_data
= (sip_conn_obj_pvt_t
*)*obj_val
;
143 if (pvt_data
== NULL
) {
147 (void) pthread_mutex_lock(&pvt_data
->sip_conn_obj_cache_lock
);
149 if (pvt_data
->sip_conn_obj_cache
== NULL
) {
150 pvt_data
->sip_conn_obj_cache
= xaction_list
;
152 xaction_list
->next
= pvt_data
->sip_conn_obj_cache
;
153 pvt_data
->sip_conn_obj_cache
->prev
= xaction_list
;
154 pvt_data
->sip_conn_obj_cache
= xaction_list
;
156 sip_refhold_conn(obj
);
157 sip_trans
->sip_xaction_conn_obj
= obj
;
158 (void) pthread_mutex_unlock(&pvt_data
->sip_conn_obj_cache_lock
);
163 * Walk thru the list of transactions that have cached this obj and
164 * and return true if 'cobj' is one of them.
167 sip_is_conn_obj_cache(sip_conn_object_t obj
, void *cobj
)
170 sip_conn_obj_pvt_t
*pvt_data
;
171 sip_conn_cache_t
*xaction_list
;
172 sip_xaction_t
*trans
;
173 sip_xaction_t
*ctrans
= (sip_xaction_t
*)cobj
;
175 obj_val
= (void *)obj
;
176 pvt_data
= (sip_conn_obj_pvt_t
*)*obj_val
;
177 if (pvt_data
== NULL
)
179 (void) pthread_mutex_lock(&pvt_data
->sip_conn_obj_cache_lock
);
180 xaction_list
= pvt_data
->sip_conn_obj_cache
;
181 while (xaction_list
!= NULL
) {
182 trans
= (sip_xaction_t
*)xaction_list
->obj
;
183 if (ctrans
!= trans
) {
184 xaction_list
= xaction_list
->next
;
187 (void) pthread_mutex_unlock(&pvt_data
->sip_conn_obj_cache_lock
);
190 (void) pthread_mutex_unlock(&pvt_data
->sip_conn_obj_cache_lock
);
196 * Walk thru the list of transactions that have cached this obj and
200 sip_del_conn_obj_cache(sip_conn_object_t obj
, void *cobj
)
203 sip_conn_obj_pvt_t
*pvt_data
;
204 sip_conn_cache_t
*xaction_list
;
205 sip_conn_cache_t
*tmp_list
;
206 sip_xaction_t
*trans
;
207 sip_xaction_t
*ctrans
= NULL
;
210 ctrans
= (sip_xaction_t
*)cobj
;
212 obj_val
= (void *)obj
;
213 pvt_data
= (sip_conn_obj_pvt_t
*)*obj_val
;
214 if (pvt_data
== NULL
) { /* ASSERT FALSE if ctrans != NULL?? */
215 if (ctrans
!= NULL
) {
216 sip_refrele_conn(obj
);
217 ctrans
->sip_xaction_conn_obj
= NULL
;
221 (void) pthread_mutex_lock(&pvt_data
->sip_conn_obj_cache_lock
);
222 xaction_list
= pvt_data
->sip_conn_obj_cache
;
223 while (xaction_list
!= NULL
) {
224 tmp_list
= xaction_list
;
225 trans
= (sip_xaction_t
*)xaction_list
->obj
;
226 assert(trans
!= NULL
);
227 if (ctrans
!= NULL
&& ctrans
!= trans
) {
228 xaction_list
= xaction_list
->next
;
232 (void) pthread_mutex_lock(&trans
->sip_xaction_mutex
);
233 assert(trans
->sip_xaction_conn_obj
== obj
);
234 sip_refrele_conn(obj
);
235 trans
->sip_xaction_conn_obj
= NULL
;
237 (void) pthread_mutex_unlock(&trans
->sip_xaction_mutex
);
238 xaction_list
= xaction_list
->next
;
241 * Take the obj out of the list
243 if (tmp_list
== pvt_data
->sip_conn_obj_cache
) {
244 if (xaction_list
== NULL
) {
245 pvt_data
->sip_conn_obj_cache
= NULL
;
247 xaction_list
->prev
= NULL
;
248 pvt_data
->sip_conn_obj_cache
= xaction_list
;
250 } else if (xaction_list
== NULL
) {
251 assert(tmp_list
->prev
!= NULL
);
252 tmp_list
->prev
->next
= NULL
;
254 assert(tmp_list
->prev
!= NULL
);
255 tmp_list
->prev
->next
= xaction_list
;
256 xaction_list
->prev
= tmp_list
->prev
;
258 tmp_list
->prev
= NULL
;
259 tmp_list
->next
= NULL
;
260 tmp_list
->obj
= NULL
;
264 (void) pthread_mutex_unlock(&pvt_data
->sip_conn_obj_cache_lock
);
268 * Check for a transaction match. Passed to sip_hash_find().
271 sip_xaction_match(void *obj
, void *hindex
)
273 sip_xaction_t
*tmp
= (sip_xaction_t
*)obj
;
275 tmp
= (sip_xaction_t
*)obj
;
277 if (SIP_IS_XACTION_TERMINATED(tmp
->sip_xaction_state
))
279 if (bcmp(tmp
->sip_xaction_hash_digest
, hindex
,
280 sizeof (tmp
->sip_xaction_hash_digest
)) == 0) {
281 SIP_XACTION_REFCNT_INCR(tmp
);
291 static sip_xaction_t
*
292 sip_xaction_find(char *branchid
, _sip_msg_t
*msg
, int which
)
295 uint16_t hash_index
[8];
299 sip_message_type_t
*sip_msg_info
;
301 sip_msg_info
= msg
->sip_msg_req_res
;
302 method
= sip_get_callseq_method((sip_msg_t
)msg
, &error
);
307 * If we are getting a ACK/CANCEL we need to match with the
308 * corresponding INVITE, if any.
310 if (sip_msg_info
->is_request
&& which
== SIP_SERVER_TRANSACTION
&&
311 (method
== ACK
|| method
== CANCEL
)) {
314 if (sip_find_md5_digest(branchid
, msg
, hash_index
, method
) != 0)
316 hindex
= SIP_DIGEST_TO_HASH(hash_index
);
317 tmp
= (sip_xaction_t
*)sip_hash_find(sip_xaction_hash
,
318 (void *)hash_index
, hindex
, sip_xaction_match
);
323 * create a transaction.
325 static sip_xaction_t
*
326 sip_xaction_create(sip_conn_object_t obj
, _sip_msg_t
*msg
, char *branchid
,
329 sip_xaction_t
*trans
;
330 sip_message_type_t
*sip_msg_info
;
335 int timer1
= sip_timer_T1
;
336 int timer4
= sip_timer_T4
;
337 int timerd
= sip_timer_TD
;
342 * Make sure we are not creating a transaction for
345 trans
= (sip_xaction_t
*)malloc(sizeof (sip_xaction_t
));
351 bzero(trans
, sizeof (sip_xaction_t
));
352 if (branchid
== NULL
) {
353 trans
->sip_xaction_branch_id
= (char *)sip_branchid(NULL
);
354 if (trans
->sip_xaction_branch_id
== NULL
) {
361 trans
->sip_xaction_branch_id
= (char *)malloc(strlen(branchid
)
363 if (trans
->sip_xaction_branch_id
== NULL
) {
369 (void) strncpy(trans
->sip_xaction_branch_id
, branchid
,
371 trans
->sip_xaction_branch_id
[strlen(branchid
)] = '\0';
373 (void) pthread_mutex_init(&trans
->sip_xaction_mutex
, NULL
);
374 SIP_MSG_REFCNT_INCR(msg
);
375 trans
->sip_xaction_orig_msg
= msg
;
376 assert(msg
->sip_msg_req_res
!= NULL
);
377 sip_msg_info
= msg
->sip_msg_req_res
;
378 if (sip_msg_info
->is_request
) {
379 method
= sip_msg_info
->sip_req_method
;
381 method
= sip_get_callseq_method((sip_msg_t
)msg
, &ret
);
383 free(trans
->sip_xaction_branch_id
);
389 if (method
== INVITE
)
390 state
= SIP_SRV_INV_PROCEEDING
;
392 state
= SIP_SRV_TRYING
;
394 trans
->sip_xaction_method
= method
;
395 trans
->sip_xaction_state
= state
;
398 * Get connection object specific timeouts, if present
400 if (sip_conn_timer1
!= NULL
)
401 timer1
= sip_conn_timer1(obj
);
402 if (sip_conn_timer4
!= NULL
)
403 timer4
= sip_conn_timer4(obj
);
404 if (sip_conn_timerd
!= NULL
)
405 timerd
= sip_conn_timerd(obj
);
407 SIP_INIT_TIMER(trans
->sip_xaction_TA
, 2 * timer1
);
408 SIP_INIT_TIMER(trans
->sip_xaction_TB
, 64 * timer1
)
409 SIP_INIT_TIMER(trans
->sip_xaction_TD
, timerd
);
410 SIP_INIT_TIMER(trans
->sip_xaction_TE
, timer1
);
411 SIP_INIT_TIMER(trans
->sip_xaction_TF
, 64 * timer1
);
412 SIP_INIT_TIMER(trans
->sip_xaction_TG
, 2 * timer1
);
413 SIP_INIT_TIMER(trans
->sip_xaction_TH
, 64 * timer1
);
414 SIP_INIT_TIMER(trans
->sip_xaction_TI
, timer4
);
415 SIP_INIT_TIMER(trans
->sip_xaction_TJ
, 64 * timer1
);
416 SIP_INIT_TIMER(trans
->sip_xaction_TK
, timer4
);
418 if ((ret
= sip_xaction_add(trans
, branchid
, msg
, method
)) != 0) {
419 (void) pthread_mutex_destroy(&trans
->sip_xaction_mutex
);
420 free(trans
->sip_xaction_branch_id
);
426 if (sip_xaction_ulp_state_cb
!= NULL
&&
427 prev_state
!= trans
->sip_xaction_state
) {
428 sip_xaction_ulp_state_cb((sip_transaction_t
)trans
,
429 (sip_msg_t
)msg
, prev_state
, trans
->sip_xaction_state
);
435 * Find a transaction, create if asked for
438 sip_xaction_get(sip_conn_object_t obj
, sip_msg_t msg
, boolean_t create
,
439 int which
, int *error
)
442 sip_xaction_t
*sip_trans
;
444 sip_message_type_t
*sip_msg_info
;
449 _msg
= (_sip_msg_t
*)msg
;
450 sip_msg_info
= ((_sip_msg_t
*)msg
)->sip_msg_req_res
;
452 branchid
= sip_get_branchid(msg
, NULL
);
453 sip_trans
= sip_xaction_find(branchid
, _msg
, which
);
454 if (sip_trans
== NULL
&& create
) {
456 * If we are sending a request, must be conformant to RFC 3261.
458 if (sip_msg_info
->is_request
&&
459 (branchid
== NULL
|| strncmp(branchid
,
460 RFC_3261_BRANCH
, strlen(RFC_3261_BRANCH
) != 0))) {
466 sip_trans
= sip_xaction_create(obj
, _msg
, branchid
, error
);
467 if (sip_trans
!= NULL
)
468 SIP_XACTION_REFCNT_INCR(sip_trans
);
476 * Delete a transaction if the reference count is 0. Passed to
480 sip_xaction_remove(void *obj
, void *hindex
, int *found
)
482 sip_xaction_t
*tmp
= (sip_xaction_t
*)obj
;
484 sip_msg_chain_t
*msg_chain
;
485 sip_msg_chain_t
*nmsg_chain
;
488 tmp
= (sip_xaction_t
*)obj
;
489 (void) pthread_mutex_lock(&tmp
->sip_xaction_mutex
);
490 if (bcmp(tmp
->sip_xaction_hash_digest
, hindex
,
491 sizeof (tmp
->sip_xaction_hash_digest
)) == 0) {
493 if (tmp
->sip_xaction_ref_cnt
!= 0) {
494 (void) pthread_mutex_unlock(&tmp
->sip_xaction_mutex
);
497 (void) pthread_mutex_destroy(&tmp
->sip_xaction_mutex
);
498 SIP_CANCEL_TIMER(tmp
->sip_xaction_TA
);
499 SIP_CANCEL_TIMER(tmp
->sip_xaction_TB
);
500 SIP_CANCEL_TIMER(tmp
->sip_xaction_TD
);
501 SIP_CANCEL_TIMER(tmp
->sip_xaction_TE
);
502 SIP_CANCEL_TIMER(tmp
->sip_xaction_TF
);
503 SIP_CANCEL_TIMER(tmp
->sip_xaction_TG
);
504 SIP_CANCEL_TIMER(tmp
->sip_xaction_TH
);
505 SIP_CANCEL_TIMER(tmp
->sip_xaction_TI
);
506 SIP_CANCEL_TIMER(tmp
->sip_xaction_TJ
);
507 SIP_CANCEL_TIMER(tmp
->sip_xaction_TK
);
508 sip_write_to_log((void *)tmp
, SIP_TRANSACTION_LOG
, NULL
, 0);
509 free(tmp
->sip_xaction_branch_id
);
510 if (tmp
->sip_xaction_last_msg
!= NULL
) {
511 SIP_MSG_REFCNT_DECR(tmp
->sip_xaction_last_msg
);
512 tmp
->sip_xaction_last_msg
= NULL
;
514 if (tmp
->sip_xaction_orig_msg
!= NULL
) {
515 SIP_MSG_REFCNT_DECR(tmp
->sip_xaction_orig_msg
);
516 tmp
->sip_xaction_orig_msg
= NULL
;
518 if (tmp
->sip_xaction_conn_obj
!= NULL
) {
519 sip_del_conn_obj_cache(tmp
->sip_xaction_conn_obj
,
523 * If the transaction logging is disabled before we could
524 * write the captured messages into the transaction log, then
525 * we need to free those captured messsages
527 for (count
= 0; count
<= SIP_SRV_NONINV_TERMINATED
; count
++) {
528 msg_chain
= tmp
->sip_xaction_log
[count
].sip_msgs
;
529 while (msg_chain
!= NULL
) {
530 nmsg_chain
= msg_chain
->next
;
531 free(msg_chain
->sip_msg
);
533 msg_chain
= nmsg_chain
;
539 (void) pthread_mutex_unlock(&tmp
->sip_xaction_mutex
);
544 * Delete a SIP transaction
547 sip_xaction_delete(sip_xaction_t
*trans
)
551 (void) pthread_mutex_lock(&trans
->sip_xaction_mutex
);
552 hindex
= SIP_DIGEST_TO_HASH(trans
->sip_xaction_hash_digest
);
553 if (trans
->sip_xaction_ref_cnt
!= 0) {
554 (void) pthread_mutex_unlock(&trans
->sip_xaction_mutex
);
557 (void) pthread_mutex_unlock(&trans
->sip_xaction_mutex
);
558 sip_hash_delete(sip_xaction_hash
, trans
->sip_xaction_hash_digest
,
559 hindex
, sip_xaction_remove
);
563 * Add a SIP transaction into the hash list.
566 sip_xaction_add(sip_xaction_t
*trans
, char *branchid
, _sip_msg_t
*msg
,
569 uint16_t hash_index
[8];
571 if (sip_find_md5_digest(branchid
, msg
, hash_index
, method
) != 0)
575 * trans is not in the list as yet, so no need to hold the lock
577 bcopy(hash_index
, trans
->sip_xaction_hash_digest
, sizeof (hash_index
));
579 if (sip_hash_add(sip_xaction_hash
, (void *)trans
,
580 SIP_DIGEST_TO_HASH(hash_index
)) != 0) {
588 * Given a state, return the string - This is mostly for debug purposes
591 sip_get_xaction_state(int state
)
594 case SIP_NEW_TRANSACTION
:
595 return ("SIP_NEW_TRANSACTION");
596 case SIP_CLNT_CALLING
:
597 return ("SIP_CLNT_CALLING");
598 case SIP_CLNT_INV_PROCEEDING
:
599 return ("SIP_CLNT_INV_PROCEEDING");
600 case SIP_CLNT_INV_TERMINATED
:
601 return ("SIP_CLNT_INV_TERMINATED");
602 case SIP_CLNT_INV_COMPLETED
:
603 return ("SIP_CLNT_INV_COMPLETED");
604 case SIP_CLNT_TRYING
:
605 return ("SIP_CLNT_TRYING");
606 case SIP_CLNT_NONINV_PROCEEDING
:
607 return ("SIP_CLNT_NONINV_PROCEEDING");
608 case SIP_CLNT_NONINV_TERMINATED
:
609 return ("SIP_CLNT_NONINV_TERMINATED");
610 case SIP_CLNT_NONINV_COMPLETED
:
611 return ("SIP_CLNT_NONINV_COMPLETED");
612 case SIP_SRV_INV_PROCEEDING
:
613 return ("SIP_SRV_INV_PROCEEDING");
614 case SIP_SRV_INV_COMPLETED
:
615 return ("SIP_SRV_INV_COMPLETED");
616 case SIP_SRV_CONFIRMED
:
617 return ("SIP_SRV_CONFIRMED");
618 case SIP_SRV_INV_TERMINATED
:
619 return ("SIP_SRV_INV_TERMINATED");
621 return ("SIP_SRV_TRYING");
622 case SIP_SRV_NONINV_PROCEEDING
:
623 return ("SIP_SRV_NONINV_PROCEEDING");
624 case SIP_SRV_NONINV_COMPLETED
:
625 return ("SIP_SRV_NONINV_COMPLETED");
626 case SIP_SRV_NONINV_TERMINATED
:
627 return ("SIP_SRV_NONINV_TERMINATED");
634 * Initialize the hash table etc.
637 sip_xaction_init(int (*ulp_trans_err
)(sip_transaction_t
, int, void *),
638 void (*ulp_state_cb
)(sip_transaction_t
, sip_msg_t
, int, int))
642 for (cnt
= 0; cnt
< SIP_HASH_SZ
; cnt
++) {
643 sip_xaction_hash
[cnt
].hash_count
= 0;
644 sip_xaction_hash
[cnt
].hash_head
= NULL
;
645 sip_xaction_hash
[cnt
].hash_tail
= NULL
;
646 (void) pthread_mutex_init(
647 &sip_xaction_hash
[cnt
].sip_hash_mutex
, NULL
);
649 if (ulp_trans_err
!= NULL
)
650 sip_xaction_ulp_trans_err
= ulp_trans_err
;
651 if (ulp_state_cb
!= NULL
)
652 sip_xaction_ulp_state_cb
= ulp_state_cb
;