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