sip_dialog_ui.c revision 4641:43d47ccda746
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 */
43sip_msg_t
44sip_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_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);
113err_ret:
114	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
115	sip_free_msg(sip_msg);
116	return (NULL);
117}
118
119/*
120 * Get the Dialog method
121 */
122int
123sip_get_dialog_method(sip_dialog_t dialog, int *error)
124{
125	_sip_dialog_t	*_dialog;
126
127	if (error != NULL)
128		*error = 0;
129	if (!sip_manage_dialog) {
130		if (error != NULL)
131			*error = EINVAL;
132		return (0);
133	}
134	if (dialog == NULL) {
135		if (error != NULL)
136			*error = EINVAL;
137		return (0);
138	}
139	_dialog = (_sip_dialog_t *)dialog;
140	return (_dialog->sip_dlg_method);
141}
142
143/*
144 * Get the Dialog state
145 */
146int
147sip_get_dialog_state(sip_dialog_t dialog, int *error)
148{
149	_sip_dialog_t	*_dialog;
150
151	if (error != NULL)
152		*error = 0;
153	if (!sip_manage_dialog) {
154		if (error != NULL)
155			*error = EINVAL;
156		return (0);
157	}
158	if (dialog == NULL) {
159		if (error != NULL)
160			*error = EINVAL;
161		return (0);
162	}
163	_dialog = (_sip_dialog_t *)dialog;
164	return (_dialog->sip_dlg_state);
165}
166
167/*
168 * Return the dialog callid
169 */
170const sip_str_t *
171sip_get_dialog_callid(sip_dialog_t dialog, int *error)
172{
173	_sip_dialog_t		*_dialog;
174	const struct sip_value	*val;
175	const sip_str_t		*callid = NULL;
176
177	if (error != NULL)
178		*error = 0;
179	if (!sip_manage_dialog || dialog == NULL) {
180		if (error != NULL)
181			*error = EINVAL;
182		return (NULL);
183	}
184	_dialog = (_sip_dialog_t *)dialog;
185	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
186	if (dialog->sip_dlg_call_id != NULL) {
187		val = sip_get_header_value(_dialog->sip_dlg_call_id, error);
188		if (val == NULL) {
189			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
190			return (NULL);
191		}
192		callid = &((sip_hdr_value_t *)val)->str_val;
193	}
194	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
195	return (callid);
196}
197
198/*
199 * Return the dialog localtag.
200 */
201const sip_str_t *
202sip_get_dialog_local_tag(sip_dialog_t dialog, int *error)
203{
204	_sip_dialog_t		*_dialog;
205	const sip_str_t		*ltag = NULL;
206	const struct sip_value	*val;
207
208	if (error != NULL)
209		*error = 0;
210	if (!sip_manage_dialog || dialog == NULL) {
211		if (error != NULL)
212			*error = EINVAL;
213		return (NULL);
214	}
215	_dialog = (_sip_dialog_t *)dialog;
216	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
217	if (dialog->sip_dlg_local_uri_tag != NULL) {
218		val = sip_get_header_value(_dialog->sip_dlg_local_uri_tag,
219		    error);
220		if (val == NULL) {
221			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
222			return (NULL);
223		}
224		ltag = sip_get_param_value((sip_header_value_t)val, "tag",
225		    error);
226	}
227	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
228	return (ltag);
229}
230
231/*
232 * Return the dialog remotetag
233 */
234const sip_str_t *
235sip_get_dialog_remote_tag(sip_dialog_t dialog, int *error)
236{
237	_sip_dialog_t		*_dialog;
238	const sip_str_t		*ttag = NULL;
239	const struct sip_value	*val;
240
241	if (error != NULL)
242		*error = 0;
243	if (!sip_manage_dialog || dialog == NULL) {
244		if (error != NULL)
245			*error = EINVAL;
246		return (NULL);
247	}
248	_dialog = (_sip_dialog_t *)dialog;
249	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
250	if (dialog->sip_dlg_remote_uri_tag != NULL) {
251		val = sip_get_header_value(_dialog->sip_dlg_remote_uri_tag,
252		    error);
253		if (val == NULL) {
254			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
255			return (NULL);
256		}
257		ttag = sip_get_param_value((sip_header_value_t)val, "tag",
258		    error);
259	}
260	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
261
262	return (ttag);
263}
264
265/*
266 * Return the dialog localuri.
267 */
268const struct sip_uri *
269sip_get_dialog_local_uri(sip_dialog_t dialog, int *error)
270{
271	_sip_dialog_t		*_dialog;
272	const _sip_uri_t	*luri = NULL;
273	const struct sip_value	*val;
274
275	if (error != NULL)
276		*error = 0;
277	if (!sip_manage_dialog || dialog == NULL) {
278		if (error != NULL)
279			*error = EINVAL;
280		return (NULL);
281	}
282	_dialog = (_sip_dialog_t *)dialog;
283	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
284	if (dialog->sip_dlg_local_uri_tag != NULL) {
285		val = sip_get_header_value(_dialog->sip_dlg_local_uri_tag,
286		    error);
287		if (val == NULL) {
288			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
289			return (NULL);
290		}
291		luri = val->sip_value_parse_uri;
292	}
293	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
294
295	return ((sip_uri_t)luri);
296}
297
298/*
299 * Return the dialog remoteuri.
300 */
301const struct sip_uri *
302sip_get_dialog_remote_uri(sip_dialog_t dialog, int *error)
303{
304	_sip_dialog_t		*_dialog;
305	const _sip_uri_t	*ruri = NULL;
306	const struct sip_value	*val;
307
308	if (error != NULL)
309		*error = 0;
310	if (!sip_manage_dialog || dialog == NULL) {
311		if (error != NULL)
312			*error = EINVAL;
313		return (NULL);
314	}
315	_dialog = (_sip_dialog_t *)dialog;
316	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
317	if (dialog->sip_dlg_remote_uri_tag != NULL) {
318		val = sip_get_header_value(dialog->sip_dlg_remote_uri_tag,
319		    error);
320		if (val == NULL) {
321			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
322			return (NULL);
323		}
324		ruri = val->sip_value_parse_uri;
325	}
326	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
327	return ((sip_uri_t)ruri);
328}
329
330/*
331 * Return the dialog remotetarg.
332 */
333const struct sip_uri *
334sip_get_dialog_remote_target_uri(sip_dialog_t dialog, int *error)
335{
336	_sip_dialog_t		*_dialog;
337	const struct sip_uri	*rtarg = NULL;
338	const struct sip_value	*val;
339
340	if (error != NULL)
341		*error = 0;
342	if (!sip_manage_dialog || dialog == NULL) {
343		if (error != NULL)
344			*error = EINVAL;
345		return (NULL);
346	}
347	_dialog = (_sip_dialog_t *)dialog;
348	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
349	if (dialog->sip_dlg_remote_target != NULL) {
350		val = sip_get_header_value(_dialog->sip_dlg_remote_target,
351		    error);
352		if (val == NULL) {
353			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
354			return (NULL);
355		}
356		rtarg = val->sip_value_parse_uri;
357	}
358	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
359
360	return ((sip_uri_t)rtarg);
361}
362
363/*
364 * Return the dialog route set
365 */
366const sip_str_t *
367sip_get_dialog_route_set(sip_dialog_t dialog, int *error)
368{
369	_sip_dialog_t		*_dialog;
370
371	if (error != NULL)
372		*error = 0;
373	if (!sip_manage_dialog || dialog == NULL) {
374		if (error != NULL)
375			*error = EINVAL;
376		return (NULL);
377	}
378	_dialog = (_sip_dialog_t *)dialog;
379	if (_dialog->sip_dlg_rset.sip_str_len > 0)
380		return (&_dialog->sip_dlg_rset);
381	return (NULL);
382}
383
384/*
385 * Return the dialog secure
386 */
387boolean_t
388sip_is_dialog_secure(sip_dialog_t dialog, int *error)
389{
390	_sip_dialog_t	*_dialog;
391	boolean_t	issecure;
392
393	if (error != NULL)
394		*error = 0;
395	if (!sip_manage_dialog || dialog == NULL) {
396		if (error != NULL)
397			*error = EINVAL;
398		return (B_FALSE);
399	}
400	_dialog = (_sip_dialog_t *)dialog;
401	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
402	issecure = _dialog->sip_dlg_secure;
403	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
404	return (issecure);
405}
406
407/*
408 * Return the dialog local cseq
409 */
410uint32_t
411sip_get_dialog_local_cseq(sip_dialog_t dialog, int *error)
412{
413	_sip_dialog_t	*_dialog;
414	uint32_t	cseq;
415
416	if (error != NULL)
417		*error = 0;
418	if (!sip_manage_dialog || dialog == NULL) {
419		if (error != NULL)
420			*error = EINVAL;
421		return (0);
422	}
423	_dialog = (_sip_dialog_t *)dialog;
424	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
425	cseq = _dialog->sip_dlg_local_cseq;
426	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
427	return (cseq);
428}
429
430/*
431 * Return the dialog remote cseq
432 */
433uint32_t
434sip_get_dialog_remote_cseq(sip_dialog_t dialog, int *error)
435{
436	_sip_dialog_t	*_dialog;
437	uint32_t	cseq;
438
439	if (error != NULL)
440		*error = 0;
441	if (!sip_manage_dialog || dialog == NULL) {
442		if (error != NULL)
443			*error = EINVAL;
444		return (0);
445	}
446	_dialog = (_sip_dialog_t *)dialog;
447	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
448	cseq = _dialog->sip_dlg_remote_cseq;
449	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
450	return (cseq);
451}
452
453/*
454 * Return the dialog type
455 */
456int
457sip_get_dialog_type(sip_dialog_t dialog, int *error)
458{
459	_sip_dialog_t	*_dialog;
460	int		type;
461
462	if (error != NULL)
463		*error = 0;
464	if (!sip_manage_dialog || dialog == NULL) {
465		if (error != NULL)
466			*error = EINVAL;
467		return (-1);
468	}
469	_dialog = (_sip_dialog_t *)dialog;
470	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
471	type = _dialog->sip_dlg_type;
472	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
473	return (type);
474}
475
476
477/*
478 * Partial dialog ?
479 */
480boolean_t
481sip_incomplete_dialog(sip_dialog_t dialog)
482{
483	_sip_dialog_t	*_dialog;
484	boolean_t	isnew;
485
486	if (!sip_manage_dialog || dialog == NULL)
487		return (B_FALSE);
488	_dialog = (_sip_dialog_t *)dialog;
489	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
490	isnew = _dialog->sip_dlg_state == SIP_DLG_NEW;
491	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
492	return (isnew);
493}
494
495/*
496 * Hold dialog
497 */
498void
499sip_hold_dialog(sip_dialog_t dialog)
500{
501	_sip_dialog_t	*_dialog;
502
503	if (!sip_manage_dialog || dialog == NULL)
504		return;
505	_dialog = (_sip_dialog_t *)dialog;
506	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
507	SIP_DLG_REFCNT_INCR(_dialog);
508	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
509}
510
511/*
512 * Release dialog
513 */
514void
515sip_release_dialog(sip_dialog_t dialog)
516{
517	_sip_dialog_t	*_dialog;
518
519	if (!sip_manage_dialog || dialog == NULL)
520		return;
521	_dialog = (_sip_dialog_t *)dialog;
522	SIP_DLG_REFCNT_DECR(_dialog);
523}
524
525/*
526 * Delete a dialog
527 */
528void
529sip_delete_dialog(sip_dialog_t dialog)
530{
531	if (!sip_manage_dialog || dialog == NULL)
532		return;
533	sip_dialog_terminate(dialog, NULL);
534}
535