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