xref: /illumos-gate/usr/src/lib/libsip/common/sip_dialog_ui.c (revision 943efbc33954e332318b6365bf27037c05bff72c)
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 2008 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_local_contact, 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  * Create a request using the state maintained in the dialog. The request will
123  * not have Contact header.
124  */
125 sip_msg_t
126 sip_create_dialog_req_nocontact(sip_method_t method, sip_dialog_t dialog,
127     char *transport, char *sent_by, int sent_by_port, char *via_param,
128     uint32_t maxforward, int cseq)
129 {
130 	sip_msg_t	sip_msg;
131 
132 	sip_msg = sip_create_dialog_req(method, dialog, transport, sent_by,
133 	    sent_by_port, via_param, maxforward, cseq);
134 	if (sip_msg != NULL) {
135 		if (sip_delete_header_by_name(sip_msg, SIP_CONTACT) != 0) {
136 			sip_free_msg(sip_msg);
137 			return (NULL);
138 		}
139 	}
140 
141 	return (sip_msg);
142 }
143 
144 /*
145  * Get the Dialog method
146  */
147 int
148 sip_get_dialog_method(sip_dialog_t dialog, int *error)
149 {
150 	_sip_dialog_t	*_dialog;
151 
152 	if (error != NULL)
153 		*error = 0;
154 	if (!sip_manage_dialog) {
155 		if (error != NULL)
156 			*error = EINVAL;
157 		return (0);
158 	}
159 	if (dialog == NULL) {
160 		if (error != NULL)
161 			*error = EINVAL;
162 		return (0);
163 	}
164 	_dialog = (_sip_dialog_t *)dialog;
165 	return (_dialog->sip_dlg_method);
166 }
167 
168 /*
169  * Get the Dialog state
170  */
171 int
172 sip_get_dialog_state(sip_dialog_t dialog, int *error)
173 {
174 	_sip_dialog_t	*_dialog;
175 
176 	if (error != NULL)
177 		*error = 0;
178 	if (!sip_manage_dialog) {
179 		if (error != NULL)
180 			*error = EINVAL;
181 		return (0);
182 	}
183 	if (dialog == NULL) {
184 		if (error != NULL)
185 			*error = EINVAL;
186 		return (0);
187 	}
188 	_dialog = (_sip_dialog_t *)dialog;
189 	return (_dialog->sip_dlg_state);
190 }
191 
192 /*
193  * Return the dialog callid
194  */
195 const sip_str_t *
196 sip_get_dialog_callid(sip_dialog_t dialog, int *error)
197 {
198 	_sip_dialog_t		*_dialog;
199 	const struct sip_value	*val;
200 	const sip_str_t		*callid = NULL;
201 
202 	if (error != NULL)
203 		*error = 0;
204 	if (!sip_manage_dialog || dialog == NULL) {
205 		if (error != NULL)
206 			*error = EINVAL;
207 		return (NULL);
208 	}
209 	_dialog = (_sip_dialog_t *)dialog;
210 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
211 	if (dialog->sip_dlg_call_id != NULL) {
212 		val = sip_get_header_value(_dialog->sip_dlg_call_id, error);
213 		if (val == NULL) {
214 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
215 			return (NULL);
216 		}
217 		callid = &((sip_hdr_value_t *)val)->str_val;
218 	}
219 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
220 	return (callid);
221 }
222 
223 /*
224  * Return the dialog localtag.
225  */
226 const sip_str_t *
227 sip_get_dialog_local_tag(sip_dialog_t dialog, int *error)
228 {
229 	_sip_dialog_t		*_dialog;
230 	const sip_str_t		*ltag = NULL;
231 	const struct sip_value	*val;
232 
233 	if (error != NULL)
234 		*error = 0;
235 	if (!sip_manage_dialog || dialog == NULL) {
236 		if (error != NULL)
237 			*error = EINVAL;
238 		return (NULL);
239 	}
240 	_dialog = (_sip_dialog_t *)dialog;
241 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
242 	if (dialog->sip_dlg_local_uri_tag != NULL) {
243 		val = sip_get_header_value(_dialog->sip_dlg_local_uri_tag,
244 		    error);
245 		if (val == NULL) {
246 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
247 			return (NULL);
248 		}
249 		ltag = sip_get_param_value((sip_header_value_t)val, "tag",
250 		    error);
251 	}
252 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
253 	return (ltag);
254 }
255 
256 /*
257  * Return the dialog remotetag
258  */
259 const sip_str_t *
260 sip_get_dialog_remote_tag(sip_dialog_t dialog, int *error)
261 {
262 	_sip_dialog_t		*_dialog;
263 	const sip_str_t		*ttag = NULL;
264 	const struct sip_value	*val;
265 
266 	if (error != NULL)
267 		*error = 0;
268 	if (!sip_manage_dialog || dialog == NULL) {
269 		if (error != NULL)
270 			*error = EINVAL;
271 		return (NULL);
272 	}
273 	_dialog = (_sip_dialog_t *)dialog;
274 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
275 	if (dialog->sip_dlg_remote_uri_tag != NULL) {
276 		val = sip_get_header_value(_dialog->sip_dlg_remote_uri_tag,
277 		    error);
278 		if (val == NULL) {
279 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
280 			return (NULL);
281 		}
282 		ttag = sip_get_param_value((sip_header_value_t)val, "tag",
283 		    error);
284 	}
285 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
286 
287 	return (ttag);
288 }
289 
290 /*
291  * Return the dialog localuri.
292  */
293 const struct sip_uri *
294 sip_get_dialog_local_uri(sip_dialog_t dialog, int *error)
295 {
296 	_sip_dialog_t		*_dialog;
297 	const _sip_uri_t	*luri = NULL;
298 	const struct sip_value	*val;
299 
300 	if (error != NULL)
301 		*error = 0;
302 	if (!sip_manage_dialog || dialog == NULL) {
303 		if (error != NULL)
304 			*error = EINVAL;
305 		return (NULL);
306 	}
307 	_dialog = (_sip_dialog_t *)dialog;
308 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
309 	if (dialog->sip_dlg_local_uri_tag != NULL) {
310 		val = sip_get_header_value(_dialog->sip_dlg_local_uri_tag,
311 		    error);
312 		if (val == NULL) {
313 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
314 			return (NULL);
315 		}
316 		luri = val->sip_value_parse_uri;
317 	}
318 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
319 
320 	return ((sip_uri_t)luri);
321 }
322 
323 /*
324  * Return the dialog remoteuri.
325  */
326 const struct sip_uri *
327 sip_get_dialog_remote_uri(sip_dialog_t dialog, int *error)
328 {
329 	_sip_dialog_t		*_dialog;
330 	const _sip_uri_t	*ruri = NULL;
331 	const struct sip_value	*val;
332 
333 	if (error != NULL)
334 		*error = 0;
335 	if (!sip_manage_dialog || dialog == NULL) {
336 		if (error != NULL)
337 			*error = EINVAL;
338 		return (NULL);
339 	}
340 	_dialog = (_sip_dialog_t *)dialog;
341 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
342 	if (dialog->sip_dlg_remote_uri_tag != NULL) {
343 		val = sip_get_header_value(dialog->sip_dlg_remote_uri_tag,
344 		    error);
345 		if (val == NULL) {
346 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
347 			return (NULL);
348 		}
349 		ruri = val->sip_value_parse_uri;
350 	}
351 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
352 	return ((sip_uri_t)ruri);
353 }
354 
355 /*
356  * Return the dialog remotetarg.
357  */
358 const struct sip_uri *
359 sip_get_dialog_remote_target_uri(sip_dialog_t dialog, int *error)
360 {
361 	_sip_dialog_t		*_dialog;
362 	const struct sip_uri	*rtarg = NULL;
363 	const struct sip_value	*val;
364 
365 	if (error != NULL)
366 		*error = 0;
367 	if (!sip_manage_dialog || dialog == NULL) {
368 		if (error != NULL)
369 			*error = EINVAL;
370 		return (NULL);
371 	}
372 	_dialog = (_sip_dialog_t *)dialog;
373 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
374 	if (dialog->sip_dlg_remote_target != NULL) {
375 		val = sip_get_header_value(_dialog->sip_dlg_remote_target,
376 		    error);
377 		if (val == NULL) {
378 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
379 			return (NULL);
380 		}
381 		rtarg = val->sip_value_parse_uri;
382 	}
383 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
384 
385 	return ((sip_uri_t)rtarg);
386 }
387 
388 /*
389  * Return the dialog local contact uri.
390  */
391 const struct sip_uri *
392 sip_get_dialog_local_contact_uri(sip_dialog_t dialog, int *error)
393 {
394 	_sip_dialog_t		*_dialog;
395 	const struct sip_uri	*lcuri = NULL;
396 	const struct sip_value	*val;
397 
398 	if (error != NULL)
399 		*error = 0;
400 	if (!sip_manage_dialog || dialog == NULL) {
401 		if (error != NULL)
402 			*error = EINVAL;
403 		return (NULL);
404 	}
405 	_dialog = (_sip_dialog_t *)dialog;
406 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
407 	if (dialog->sip_dlg_local_contact != NULL) {
408 		val = sip_get_header_value(_dialog->sip_dlg_local_contact,
409 		    error);
410 		if (val == NULL) {
411 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
412 			return (NULL);
413 		}
414 		lcuri = val->sip_value_parse_uri;
415 	}
416 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
417 
418 	return ((sip_uri_t)lcuri);
419 }
420 
421 /*
422  * Return the dialog route set
423  */
424 const sip_str_t *
425 sip_get_dialog_route_set(sip_dialog_t dialog, int *error)
426 {
427 	_sip_dialog_t		*_dialog;
428 
429 	if (error != NULL)
430 		*error = 0;
431 	if (!sip_manage_dialog || dialog == NULL) {
432 		if (error != NULL)
433 			*error = EINVAL;
434 		return (NULL);
435 	}
436 	_dialog = (_sip_dialog_t *)dialog;
437 	if (_dialog->sip_dlg_rset.sip_str_len > 0)
438 		return (&_dialog->sip_dlg_rset);
439 	return (NULL);
440 }
441 
442 /*
443  * Return the dialog secure
444  */
445 boolean_t
446 sip_is_dialog_secure(sip_dialog_t dialog, int *error)
447 {
448 	_sip_dialog_t	*_dialog;
449 	boolean_t	issecure;
450 
451 	if (error != NULL)
452 		*error = 0;
453 	if (!sip_manage_dialog || dialog == NULL) {
454 		if (error != NULL)
455 			*error = EINVAL;
456 		return (B_FALSE);
457 	}
458 	_dialog = (_sip_dialog_t *)dialog;
459 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
460 	issecure = _dialog->sip_dlg_secure;
461 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
462 	return (issecure);
463 }
464 
465 /*
466  * Return the dialog local cseq
467  */
468 uint32_t
469 sip_get_dialog_local_cseq(sip_dialog_t dialog, int *error)
470 {
471 	_sip_dialog_t	*_dialog;
472 	uint32_t	cseq;
473 
474 	if (error != NULL)
475 		*error = 0;
476 	if (!sip_manage_dialog || dialog == NULL) {
477 		if (error != NULL)
478 			*error = EINVAL;
479 		return (0);
480 	}
481 	_dialog = (_sip_dialog_t *)dialog;
482 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
483 	cseq = _dialog->sip_dlg_local_cseq;
484 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
485 	return (cseq);
486 }
487 
488 /*
489  * Return the dialog remote cseq
490  */
491 uint32_t
492 sip_get_dialog_remote_cseq(sip_dialog_t dialog, int *error)
493 {
494 	_sip_dialog_t	*_dialog;
495 	uint32_t	cseq;
496 
497 	if (error != NULL)
498 		*error = 0;
499 	if (!sip_manage_dialog || dialog == NULL) {
500 		if (error != NULL)
501 			*error = EINVAL;
502 		return (0);
503 	}
504 	_dialog = (_sip_dialog_t *)dialog;
505 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
506 	cseq = _dialog->sip_dlg_remote_cseq;
507 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
508 	return (cseq);
509 }
510 
511 /*
512  * Return the dialog type
513  */
514 int
515 sip_get_dialog_type(sip_dialog_t dialog, int *error)
516 {
517 	_sip_dialog_t	*_dialog;
518 	int		type;
519 
520 	if (error != NULL)
521 		*error = 0;
522 	if (!sip_manage_dialog || dialog == NULL) {
523 		if (error != NULL)
524 			*error = EINVAL;
525 		return (-1);
526 	}
527 	_dialog = (_sip_dialog_t *)dialog;
528 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
529 	type = _dialog->sip_dlg_type;
530 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
531 	return (type);
532 }
533 
534 /*
535  * Return the number of messages exchanged within a dialog.
536  */
537 int
538 sip_get_dialog_msgcnt(sip_dialog_t dialog, int *error)
539 {
540 	_sip_dialog_t	*_dialog;
541 	int		nmsgs;
542 
543 	if (error != NULL)
544 		*error = 0;
545 	if (!sip_manage_dialog || dialog == NULL) {
546 		if (error != NULL)
547 			*error = EINVAL;
548 		return (-1);
549 	}
550 	_dialog = (_sip_dialog_t *)dialog;
551 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
552 	nmsgs = _dialog->sip_dlg_msgcnt;
553 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
554 	return (nmsgs);
555 }
556 
557 /*
558  * Partial dialog ?
559  */
560 boolean_t
561 sip_incomplete_dialog(sip_dialog_t dialog)
562 {
563 	_sip_dialog_t	*_dialog;
564 	boolean_t	isnew;
565 
566 	if (!sip_manage_dialog || dialog == NULL)
567 		return (B_FALSE);
568 	_dialog = (_sip_dialog_t *)dialog;
569 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
570 	isnew = _dialog->sip_dlg_state == SIP_DLG_NEW;
571 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
572 	return (isnew);
573 }
574 
575 /*
576  * Hold dialog
577  */
578 void
579 sip_hold_dialog(sip_dialog_t dialog)
580 {
581 	_sip_dialog_t	*_dialog;
582 
583 	if (!sip_manage_dialog || dialog == NULL)
584 		return;
585 	_dialog = (_sip_dialog_t *)dialog;
586 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
587 	SIP_DLG_REFCNT_INCR(_dialog);
588 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
589 }
590 
591 /*
592  * Release dialog
593  */
594 void
595 sip_release_dialog(sip_dialog_t dialog)
596 {
597 	_sip_dialog_t	*_dialog;
598 
599 	if (!sip_manage_dialog || dialog == NULL)
600 		return;
601 	_dialog = (_sip_dialog_t *)dialog;
602 	SIP_DLG_REFCNT_DECR(_dialog);
603 }
604 
605 /*
606  * Delete a dialog
607  */
608 void
609 sip_delete_dialog(sip_dialog_t dialog)
610 {
611 	if (!sip_manage_dialog || dialog == NULL)
612 		return;
613 	sip_dialog_terminate(dialog, NULL);
614 }
615