sip_dialog_ui.c revision 4702:655cbe4c8575
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_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);
115err_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 */
124int
125sip_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 */
148int
149sip_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 */
172const sip_str_t *
173sip_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 */
203const sip_str_t *
204sip_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 */
236const sip_str_t *
237sip_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 */
270const struct sip_uri *
271sip_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 */
303const struct sip_uri *
304sip_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 */
335const struct sip_uri *
336sip_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 */
368const sip_str_t *
369sip_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 */
389boolean_t
390sip_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 */
412uint32_t
413sip_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 */
435uint32_t
436sip_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 */
458int
459sip_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 */
482boolean_t
483sip_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 */
500void
501sip_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 */
516void
517sip_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 */
530void
531sip_delete_dialog(sip_dialog_t dialog)
532{
533	if (!sip_manage_dialog || dialog == NULL)
534		return;
535	sip_dialog_terminate(dialog, NULL);
536}
537