xref: /illumos-gate/usr/src/lib/libsip/common/sip_dialog_ui.c (revision 40cb5e5daa7b80bb70fcf8dadfb20f9281566331)
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 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include "sip_parse_uri.h"
30 #include "sip_msg.h"
31 #include "sip_miscdefs.h"
32 #include "sip_dialog.h"
33 #include "sip_xaction.h"
34 
35 /*
36  * Create a request using the state maintained in the dialog.
37  */
38 sip_msg_t
39 sip_create_dialog_req(sip_method_t method, sip_dialog_t dialog,
40     char *transport, char *sent_by, int sent_by_port, char *via_param,
41     uint32_t maxforward, int cseq)
42 {
43 	_sip_dialog_t	*_dialog;
44 	sip_msg_t	sip_msg;
45 	char		*uri;
46 	int		oldseq = 0;
47 
48 	if (!sip_manage_dialog || dialog == NULL || transport == NULL ||
49 	    sent_by == NULL) {
50 		return (NULL);
51 	}
52 	if ((sip_msg = sip_new_msg()) == NULL)
53 		return (NULL);
54 	_dialog = (_sip_dialog_t *)dialog;
55 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
56 	/*
57 	 * Depending on the route set, if any, the request URI could either
58 	 * be the contact URI or the 1st URI from the route set.
59 	 */
60 	uri = (char *)sip_dialog_req_uri(_dialog);
61 	if (uri == NULL)
62 		goto err_ret;
63 	if (sip_add_request_line(sip_msg, method, uri) != 0) {
64 		free(uri);
65 		goto err_ret;
66 	}
67 	free(uri);
68 	if (sip_copy_header(sip_msg, _dialog->sip_dlg_local_uri_tag, NULL) != 0)
69 		goto err_ret;
70 	if (sip_copy_header(sip_msg, _dialog->sip_dlg_remote_uri_tag, NULL) !=
71 	    0) {
72 		goto err_ret;
73 	}
74 	if (sip_copy_header(sip_msg, _dialog->sip_dlg_remote_target, NULL) != 0)
75 		goto err_ret;
76 	if (sip_add_via(sip_msg, transport, sent_by, sent_by_port, via_param) !=
77 	    0) {
78 		goto err_ret;
79 	}
80 	if (sip_add_maxforward(sip_msg, maxforward) != 0)
81 		goto err_ret;
82 	if (sip_copy_header(sip_msg, _dialog->sip_dlg_call_id, NULL) != 0)
83 		goto err_ret;
84 	if (cseq < 0) {
85 		if (_dialog->sip_dlg_local_cseq == 0)
86 			_dialog->sip_dlg_local_cseq = 1;
87 		oldseq = _dialog->sip_dlg_local_cseq;
88 		cseq = ++_dialog->sip_dlg_local_cseq;
89 	}
90 	if (sip_add_cseq(sip_msg, method, cseq) != 0) {
91 		_dialog->sip_dlg_local_cseq = oldseq;
92 		goto err_ret;
93 	}
94 	/*
95 	 * The route set, even if empty, overrides any pre-existing route set.
96 	 * If the route set is empty, the UAC MUST NOT add a Route header
97 	 * field to the request.
98 	 */
99 	(void) sip_delete_header_by_name(sip_msg, SIP_ROUTE);
100 
101 	if (_dialog->sip_dlg_route_set != NULL) {
102 		if (sip_copy_header(sip_msg, _dialog->sip_dlg_route_set,
103 		    NULL) != 0) {
104 			_dialog->sip_dlg_local_cseq = oldseq;
105 			goto err_ret;
106 		}
107 	}
108 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
109 	return (sip_msg);
110 err_ret:
111 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
112 	sip_free_msg(sip_msg);
113 	return (NULL);
114 }
115 
116 /*
117  * Get the Dialog method
118  */
119 int
120 sip_get_dialog_method(sip_dialog_t dialog, int *error)
121 {
122 	_sip_dialog_t	*_dialog;
123 
124 	if (error != NULL)
125 		*error = 0;
126 	if (!sip_manage_dialog) {
127 		if (error != NULL)
128 			*error = EINVAL;
129 		return (0);
130 	}
131 	if (dialog == NULL) {
132 		if (error != NULL)
133 			*error = EINVAL;
134 		return (0);
135 	}
136 	_dialog = (_sip_dialog_t *)dialog;
137 	return (_dialog->sip_dlg_method);
138 }
139 
140 /*
141  * Get the Dialog state
142  */
143 int
144 sip_get_dialog_state(sip_dialog_t dialog, int *error)
145 {
146 	_sip_dialog_t	*_dialog;
147 
148 	if (error != NULL)
149 		*error = 0;
150 	if (!sip_manage_dialog) {
151 		if (error != NULL)
152 			*error = EINVAL;
153 		return (0);
154 	}
155 	if (dialog == NULL) {
156 		if (error != NULL)
157 			*error = EINVAL;
158 		return (0);
159 	}
160 	_dialog = (_sip_dialog_t *)dialog;
161 	return (_dialog->sip_dlg_state);
162 }
163 
164 /*
165  * Return the dialog callid
166  */
167 const sip_str_t *
168 sip_get_dialog_callid(sip_dialog_t dialog, int *error)
169 {
170 	_sip_dialog_t		*_dialog;
171 	const struct sip_value	*val;
172 	const sip_str_t		*callid = NULL;
173 
174 	if (error != NULL)
175 		*error = 0;
176 	if (!sip_manage_dialog || dialog == NULL) {
177 		if (error != NULL)
178 			*error = EINVAL;
179 		return (NULL);
180 	}
181 	_dialog = (_sip_dialog_t *)dialog;
182 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
183 	if (dialog->sip_dlg_call_id != NULL) {
184 		val = sip_get_header_value(_dialog->sip_dlg_call_id, error);
185 		if (val == NULL) {
186 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
187 			return (NULL);
188 		}
189 		callid = &((sip_hdr_value_t *)val)->str_val;
190 	}
191 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
192 	return (callid);
193 }
194 
195 /*
196  * Return the dialog localtag.
197  */
198 const sip_str_t *
199 sip_get_dialog_local_tag(sip_dialog_t dialog, int *error)
200 {
201 	_sip_dialog_t		*_dialog;
202 	const sip_str_t		*ltag = NULL;
203 	const struct sip_value	*val;
204 
205 	if (error != NULL)
206 		*error = 0;
207 	if (!sip_manage_dialog || dialog == NULL) {
208 		if (error != NULL)
209 			*error = EINVAL;
210 		return (NULL);
211 	}
212 	_dialog = (_sip_dialog_t *)dialog;
213 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
214 	if (dialog->sip_dlg_local_uri_tag != NULL) {
215 		val = sip_get_header_value(_dialog->sip_dlg_local_uri_tag,
216 		    error);
217 		if (val == NULL) {
218 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
219 			return (NULL);
220 		}
221 		ltag = sip_get_param_value((sip_header_value_t)val, "tag",
222 		    error);
223 	}
224 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
225 	return (ltag);
226 }
227 
228 /*
229  * Return the dialog remotetag
230  */
231 const sip_str_t *
232 sip_get_dialog_remote_tag(sip_dialog_t dialog, int *error)
233 {
234 	_sip_dialog_t		*_dialog;
235 	const sip_str_t		*ttag = NULL;
236 	const struct sip_value	*val;
237 
238 	if (error != NULL)
239 		*error = 0;
240 	if (!sip_manage_dialog || dialog == NULL) {
241 		if (error != NULL)
242 			*error = EINVAL;
243 		return (NULL);
244 	}
245 	_dialog = (_sip_dialog_t *)dialog;
246 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
247 	if (dialog->sip_dlg_remote_uri_tag != NULL) {
248 		val = sip_get_header_value(_dialog->sip_dlg_remote_uri_tag,
249 		    error);
250 		if (val == NULL) {
251 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
252 			return (NULL);
253 		}
254 		ttag = sip_get_param_value((sip_header_value_t)val, "tag",
255 		    error);
256 	}
257 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
258 
259 	return (ttag);
260 }
261 
262 /*
263  * Return the dialog localuri.
264  */
265 const struct sip_uri *
266 sip_get_dialog_local_uri(sip_dialog_t dialog, int *error)
267 {
268 	_sip_dialog_t		*_dialog;
269 	const _sip_uri_t	*luri = NULL;
270 	const struct sip_value	*val;
271 
272 	if (error != NULL)
273 		*error = 0;
274 	if (!sip_manage_dialog || dialog == NULL) {
275 		if (error != NULL)
276 			*error = EINVAL;
277 		return (NULL);
278 	}
279 	_dialog = (_sip_dialog_t *)dialog;
280 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
281 	if (dialog->sip_dlg_local_uri_tag != NULL) {
282 		val = sip_get_header_value(_dialog->sip_dlg_local_uri_tag,
283 		    error);
284 		if (val == NULL) {
285 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
286 			return (NULL);
287 		}
288 		luri = val->sip_value_parse_uri;
289 	}
290 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
291 
292 	return ((sip_uri_t)luri);
293 }
294 
295 /*
296  * Return the dialog remoteuri.
297  */
298 const struct sip_uri *
299 sip_get_dialog_remote_uri(sip_dialog_t dialog, int *error)
300 {
301 	_sip_dialog_t		*_dialog;
302 	const _sip_uri_t	*ruri = NULL;
303 	const struct sip_value	*val;
304 
305 	if (error != NULL)
306 		*error = 0;
307 	if (!sip_manage_dialog || dialog == NULL) {
308 		if (error != NULL)
309 			*error = EINVAL;
310 		return (NULL);
311 	}
312 	_dialog = (_sip_dialog_t *)dialog;
313 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
314 	if (dialog->sip_dlg_remote_uri_tag != NULL) {
315 		val = sip_get_header_value(dialog->sip_dlg_remote_uri_tag,
316 		    error);
317 		if (val == NULL) {
318 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
319 			return (NULL);
320 		}
321 		ruri = val->sip_value_parse_uri;
322 	}
323 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
324 	return ((sip_uri_t)ruri);
325 }
326 
327 /*
328  * Return the dialog remotetarg.
329  */
330 const struct sip_uri *
331 sip_get_dialog_remote_target_uri(sip_dialog_t dialog, int *error)
332 {
333 	_sip_dialog_t		*_dialog;
334 	const struct sip_uri	*rtarg = NULL;
335 	const struct sip_value	*val;
336 
337 	if (error != NULL)
338 		*error = 0;
339 	if (!sip_manage_dialog || dialog == NULL) {
340 		if (error != NULL)
341 			*error = EINVAL;
342 		return (NULL);
343 	}
344 	_dialog = (_sip_dialog_t *)dialog;
345 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
346 	if (dialog->sip_dlg_remote_target != NULL) {
347 		val = sip_get_header_value(_dialog->sip_dlg_remote_target,
348 		    error);
349 		if (val == NULL) {
350 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
351 			return (NULL);
352 		}
353 		rtarg = val->sip_value_parse_uri;
354 	}
355 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
356 
357 	return ((sip_uri_t)rtarg);
358 }
359 
360 /*
361  * Return the dialog route set
362  */
363 const sip_str_t *
364 sip_get_dialog_route_set(sip_dialog_t dialog, int *error)
365 {
366 	_sip_dialog_t		*_dialog;
367 
368 	if (error != NULL)
369 		*error = 0;
370 	if (!sip_manage_dialog || dialog == NULL) {
371 		if (error != NULL)
372 			*error = EINVAL;
373 		return (NULL);
374 	}
375 	_dialog = (_sip_dialog_t *)dialog;
376 	if (_dialog->sip_dlg_rset.sip_str_len > 0)
377 		return (&_dialog->sip_dlg_rset);
378 	return (NULL);
379 }
380 
381 /*
382  * Return the dialog secure
383  */
384 boolean_t
385 sip_is_dialog_secure(sip_dialog_t dialog, int *error)
386 {
387 	_sip_dialog_t	*_dialog;
388 	boolean_t	issecure;
389 
390 	if (error != NULL)
391 		*error = 0;
392 	if (!sip_manage_dialog || dialog == NULL) {
393 		if (error != NULL)
394 			*error = EINVAL;
395 		return (B_FALSE);
396 	}
397 	_dialog = (_sip_dialog_t *)dialog;
398 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
399 	issecure = _dialog->sip_dlg_secure;
400 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
401 	return (issecure);
402 }
403 
404 /*
405  * Return the dialog local cseq
406  */
407 uint32_t
408 sip_get_dialog_local_cseq(sip_dialog_t dialog, int *error)
409 {
410 	_sip_dialog_t	*_dialog;
411 	uint32_t	cseq;
412 
413 	if (error != NULL)
414 		*error = 0;
415 	if (!sip_manage_dialog || dialog == NULL) {
416 		if (error != NULL)
417 			*error = EINVAL;
418 		return (0);
419 	}
420 	_dialog = (_sip_dialog_t *)dialog;
421 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
422 	cseq = _dialog->sip_dlg_local_cseq;
423 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
424 	return (cseq);
425 }
426 
427 /*
428  * Return the dialog remote cseq
429  */
430 uint32_t
431 sip_get_dialog_remote_cseq(sip_dialog_t dialog, int *error)
432 {
433 	_sip_dialog_t	*_dialog;
434 	uint32_t	cseq;
435 
436 	if (error != NULL)
437 		*error = 0;
438 	if (!sip_manage_dialog || dialog == NULL) {
439 		if (error != NULL)
440 			*error = EINVAL;
441 		return (0);
442 	}
443 	_dialog = (_sip_dialog_t *)dialog;
444 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
445 	cseq = _dialog->sip_dlg_remote_cseq;
446 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
447 	return (cseq);
448 }
449 
450 /*
451  * Return the dialog type
452  */
453 int
454 sip_get_dialog_type(sip_dialog_t dialog, int *error)
455 {
456 	_sip_dialog_t	*_dialog;
457 	int		type;
458 
459 	if (error != NULL)
460 		*error = 0;
461 	if (!sip_manage_dialog || dialog == NULL) {
462 		if (error != NULL)
463 			*error = EINVAL;
464 		return (-1);
465 	}
466 	_dialog = (_sip_dialog_t *)dialog;
467 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
468 	type = _dialog->sip_dlg_type;
469 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
470 	return (type);
471 }
472 
473 
474 /*
475  * Partial dialog ?
476  */
477 boolean_t
478 sip_incomplete_dialog(sip_dialog_t dialog)
479 {
480 	_sip_dialog_t	*_dialog;
481 	boolean_t	isnew;
482 
483 	if (!sip_manage_dialog || dialog == NULL)
484 		return (B_FALSE);
485 	_dialog = (_sip_dialog_t *)dialog;
486 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
487 	isnew = _dialog->sip_dlg_state == SIP_DLG_NEW;
488 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
489 	return (isnew);
490 }
491 
492 /*
493  * Hold dialog
494  */
495 void
496 sip_hold_dialog(sip_dialog_t dialog)
497 {
498 	_sip_dialog_t	*_dialog;
499 
500 	if (!sip_manage_dialog || dialog == NULL)
501 		return;
502 	_dialog = (_sip_dialog_t *)dialog;
503 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
504 	SIP_DLG_REFCNT_INCR(_dialog);
505 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
506 }
507 
508 /*
509  * Release dialog
510  */
511 void
512 sip_release_dialog(sip_dialog_t dialog)
513 {
514 	_sip_dialog_t	*_dialog;
515 
516 	if (!sip_manage_dialog || dialog == NULL)
517 		return;
518 	_dialog = (_sip_dialog_t *)dialog;
519 	SIP_DLG_REFCNT_DECR(_dialog);
520 }
521 
522 /*
523  * Delete a dialog
524  */
525 void
526 sip_delete_dialog(sip_dialog_t dialog)
527 {
528 	if (!sip_manage_dialog || dialog == NULL)
529 		return;
530 	sip_dialog_terminate(dialog, NULL);
531 }
532