1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <stdlib.h>
28 #include <assert.h>
29 #include <errno.h>
30 #include <strings.h>
31 #include <pthread.h>
32 #include <sip.h>
33 
34 #include "sip_msg.h"
35 #include "sip_miscdefs.h"
36 #include "sip_xaction.h"
37 
38 /*
39  * Hold transaction
40  */
41 void
sip_hold_trans(sip_transaction_t sip_trans)42 sip_hold_trans(sip_transaction_t sip_trans)
43 {
44 	sip_xaction_t	*_trans;
45 
46 	if (sip_trans == NULL)
47 		return;
48 	_trans = (sip_xaction_t *)sip_trans;
49 	(void) pthread_mutex_lock(&((_trans)->sip_xaction_mutex));
50 	SIP_XACTION_REFCNT_INCR(_trans);
51 	(void) pthread_mutex_unlock(&((_trans)->sip_xaction_mutex));
52 }
53 
54 /*
55  * Release transaction
56  */
57 void
sip_release_trans(sip_transaction_t sip_trans)58 sip_release_trans(sip_transaction_t sip_trans)
59 {
60 	sip_xaction_t	*_trans;
61 
62 	if (sip_trans == NULL)
63 		return;
64 	_trans = (sip_xaction_t *)sip_trans;
65 	SIP_XACTION_REFCNT_DECR(_trans);
66 }
67 
68 /*
69  * Given a message get the client/server transaction. The caller is
70  * responsible for doing a sip_release_trans().
71  */
72 const struct sip_xaction *
sip_get_trans(sip_msg_t sip_msg,int which,int * error)73 sip_get_trans(sip_msg_t sip_msg, int which, int *error)
74 {
75 	if (error != NULL)
76 		*error = 0;
77 	if (sip_msg == NULL) {
78 		if (error != NULL)
79 			*error = EINVAL;
80 		return (NULL);
81 	}
82 	return ((sip_transaction_t)sip_xaction_get(NULL, sip_msg, B_FALSE,
83 	    which, NULL));
84 }
85 
86 /*
87  * Get the last response sent for this transaction
88  */
89 const struct sip_message *
sip_get_trans_resp_msg(sip_transaction_t sip_trans,int * error)90 sip_get_trans_resp_msg(sip_transaction_t sip_trans, int *error)
91 {
92 	sip_xaction_t	*_trans;
93 
94 	if (error != NULL)
95 		*error = 0;
96 	if (sip_trans == NULL) {
97 		if (error != NULL)
98 			*error = EINVAL;
99 		return (NULL);
100 	}
101 	_trans = (sip_xaction_t *)sip_trans;
102 	if ((_trans->sip_xaction_last_msg != NULL) &&
103 	    !sip_msg_is_request((sip_msg_t)_trans->sip_xaction_last_msg,
104 	    error)) {
105 		return (_trans->sip_xaction_last_msg);
106 	} else if (!sip_msg_is_request((sip_msg_t)
107 	    _trans->sip_xaction_orig_msg, error)) {
108 		return (_trans->sip_xaction_orig_msg);
109 	}
110 	return (NULL);
111 }
112 
113 /*
114  * Get the SIP message that created this transaction
115  */
116 const struct sip_message *
sip_get_trans_orig_msg(sip_transaction_t sip_trans,int * error)117 sip_get_trans_orig_msg(sip_transaction_t sip_trans, int *error)
118 {
119 	if (error != NULL)
120 		*error = 0;
121 	if (sip_trans == NULL) {
122 		if (error != NULL)
123 			*error = EINVAL;
124 		return (NULL);
125 	}
126 	return (((sip_xaction_t *)sip_trans)->sip_xaction_orig_msg);
127 }
128 
129 /*
130  * Get the connection object that was used to send the last message for this
131  * transaction.
132  */
133 const struct sip_conn_object *
sip_get_trans_conn_obj(sip_transaction_t sip_trans,int * error)134 sip_get_trans_conn_obj(sip_transaction_t sip_trans, int *error)
135 {
136 	if (error != NULL)
137 		*error = 0;
138 	if (sip_trans == NULL) {
139 		if (error != NULL)
140 			*error = EINVAL;
141 		return (NULL);
142 	}
143 	return (((sip_xaction_t *)sip_trans)->sip_xaction_conn_obj);
144 }
145 
146 /*
147  * Get the transaction method
148  */
149 sip_method_t
sip_get_trans_method(sip_transaction_t sip_trans,int * error)150 sip_get_trans_method(sip_transaction_t sip_trans, int *error)
151 {
152 	if (error != NULL)
153 		*error = 0;
154 
155 	if (sip_trans == NULL) {
156 		if (error != NULL)
157 			*error = EINVAL;
158 		return (-1);
159 	}
160 	return (((sip_xaction_t *)sip_trans)->sip_xaction_method);
161 }
162 
163 /*
164  * Get the transaction id. Caller frees string
165  */
166 char *
sip_get_trans_branchid(sip_transaction_t trans,int * error)167 sip_get_trans_branchid(sip_transaction_t trans, int *error)
168 {
169 	sip_xaction_t	*xaction = (sip_xaction_t *)trans;
170 	char		*bid;
171 
172 	if (error != NULL)
173 		*error = 0;
174 	if (xaction == NULL || xaction->sip_xaction_branch_id == NULL) {
175 		if (error != NULL)
176 			*error = EINVAL;
177 		return (NULL);
178 	}
179 	bid = malloc(strlen(xaction->sip_xaction_branch_id) + 1);
180 	if (bid == NULL) {
181 		if (error != NULL)
182 			*error = ENOMEM;
183 		return (NULL);
184 	}
185 	(void) strncpy(bid, xaction->sip_xaction_branch_id,
186 	    strlen(xaction->sip_xaction_branch_id));
187 	bid[strlen(xaction->sip_xaction_branch_id)] = '\0';
188 	return (bid);
189 }
190 
191 /*
192  * Get the transaction state
193  */
194 int
sip_get_trans_state(sip_transaction_t trans,int * error)195 sip_get_trans_state(sip_transaction_t trans, int *error)
196 {
197 	sip_xaction_t	*xaction = (sip_xaction_t *)trans;
198 
199 	if (error != NULL)
200 		*error = 0;
201 	if (xaction == NULL) {
202 		if (error != NULL)
203 			*error = EINVAL;
204 		return (0);
205 	}
206 	return (xaction->sip_xaction_state);
207 }
208