140cb5e5dSvi /*
240cb5e5dSvi  * CDDL HEADER START
340cb5e5dSvi  *
440cb5e5dSvi  * The contents of this file are subject to the terms of the
540cb5e5dSvi  * Common Development and Distribution License (the "License").
640cb5e5dSvi  * You may not use this file except in compliance with the License.
740cb5e5dSvi  *
840cb5e5dSvi  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
940cb5e5dSvi  * or http://www.opensolaris.org/os/licensing.
1040cb5e5dSvi  * See the License for the specific language governing permissions
1140cb5e5dSvi  * and limitations under the License.
1240cb5e5dSvi  *
1340cb5e5dSvi  * When distributing Covered Code, include this CDDL HEADER in each
1440cb5e5dSvi  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1540cb5e5dSvi  * If applicable, add the following below this CDDL HEADER, with the
1640cb5e5dSvi  * fields enclosed by brackets "[]" replaced with your own identifying
1740cb5e5dSvi  * information: Portions Copyright [yyyy] [name of copyright owner]
1840cb5e5dSvi  *
1940cb5e5dSvi  * CDDL HEADER END
2040cb5e5dSvi  */
2140cb5e5dSvi 
2240cb5e5dSvi /*
23*943efbc3Sgm  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
2440cb5e5dSvi  * Use is subject to license terms.
2540cb5e5dSvi  */
2640cb5e5dSvi 
272c2c4183Svi #include <stdlib.h>
282c2c4183Svi #include <assert.h>
292c2c4183Svi #include <errno.h>
302c2c4183Svi #include <pthread.h>
312c2c4183Svi #include <sip.h>
322c2c4183Svi 
3340cb5e5dSvi #include "sip_msg.h"
3440cb5e5dSvi #include "sip_miscdefs.h"
352c2c4183Svi #include "sip_parse_uri.h"
3640cb5e5dSvi #include "sip_dialog.h"
3740cb5e5dSvi 
3840cb5e5dSvi /*
3940cb5e5dSvi  * Create a request using the state maintained in the dialog.
4040cb5e5dSvi  */
4140cb5e5dSvi sip_msg_t
sip_create_dialog_req(sip_method_t method,sip_dialog_t dialog,char * transport,char * sent_by,int sent_by_port,char * via_param,uint32_t maxforward,int cseq)4240cb5e5dSvi sip_create_dialog_req(sip_method_t method, sip_dialog_t dialog,
4340cb5e5dSvi     char *transport, char *sent_by, int sent_by_port, char *via_param,
4440cb5e5dSvi     uint32_t maxforward, int cseq)
4540cb5e5dSvi {
4640cb5e5dSvi 	_sip_dialog_t	*_dialog;
4740cb5e5dSvi 	sip_msg_t	sip_msg;
4840cb5e5dSvi 	char		*uri;
4940cb5e5dSvi 	int		oldseq = 0;
5040cb5e5dSvi 
5140cb5e5dSvi 	if (!sip_manage_dialog || dialog == NULL || transport == NULL ||
5240cb5e5dSvi 	    sent_by == NULL) {
5340cb5e5dSvi 		return (NULL);
5440cb5e5dSvi 	}
5540cb5e5dSvi 	if ((sip_msg = sip_new_msg()) == NULL)
5640cb5e5dSvi 		return (NULL);
5740cb5e5dSvi 	_dialog = (_sip_dialog_t *)dialog;
5840cb5e5dSvi 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
5940cb5e5dSvi 	/*
6040cb5e5dSvi 	 * Depending on the route set, if any, the request URI could either
6140cb5e5dSvi 	 * be the contact URI or the 1st URI from the route set.
6240cb5e5dSvi 	 */
6340cb5e5dSvi 	uri = (char *)sip_dialog_req_uri(_dialog);
6440cb5e5dSvi 	if (uri == NULL)
6540cb5e5dSvi 		goto err_ret;
6640cb5e5dSvi 	if (sip_add_request_line(sip_msg, method, uri) != 0) {
6740cb5e5dSvi 		free(uri);
6840cb5e5dSvi 		goto err_ret;
6940cb5e5dSvi 	}
7040cb5e5dSvi 	free(uri);
7140cb5e5dSvi 	if (sip_copy_header(sip_msg, _dialog->sip_dlg_local_uri_tag, NULL) != 0)
7240cb5e5dSvi 		goto err_ret;
7340cb5e5dSvi 	if (sip_copy_header(sip_msg, _dialog->sip_dlg_remote_uri_tag, NULL) !=
7440cb5e5dSvi 	    0) {
7540cb5e5dSvi 		goto err_ret;
7640cb5e5dSvi 	}
77d8a40387Sgm 	if (sip_copy_header(sip_msg, _dialog->sip_dlg_local_contact, NULL) != 0)
78d8a40387Sgm 		goto err_ret;
7940cb5e5dSvi 	if (sip_add_via(sip_msg, transport, sent_by, sent_by_port, via_param) !=
8040cb5e5dSvi 	    0) {
8140cb5e5dSvi 		goto err_ret;
8240cb5e5dSvi 	}
8340cb5e5dSvi 	if (sip_add_maxforward(sip_msg, maxforward) != 0)
8440cb5e5dSvi 		goto err_ret;
8540cb5e5dSvi 	if (sip_copy_header(sip_msg, _dialog->sip_dlg_call_id, NULL) != 0)
8640cb5e5dSvi 		goto err_ret;
8740cb5e5dSvi 	if (cseq < 0) {
8840cb5e5dSvi 		if (_dialog->sip_dlg_local_cseq == 0)
8940cb5e5dSvi 			_dialog->sip_dlg_local_cseq = 1;
9040cb5e5dSvi 		oldseq = _dialog->sip_dlg_local_cseq;
9140cb5e5dSvi 		cseq = ++_dialog->sip_dlg_local_cseq;
9240cb5e5dSvi 	}
9340cb5e5dSvi 	if (sip_add_cseq(sip_msg, method, cseq) != 0) {
9440cb5e5dSvi 		_dialog->sip_dlg_local_cseq = oldseq;
9540cb5e5dSvi 		goto err_ret;
9640cb5e5dSvi 	}
9740cb5e5dSvi 	/*
9840cb5e5dSvi 	 * The route set, even if empty, overrides any pre-existing route set.
9940cb5e5dSvi 	 * If the route set is empty, the UAC MUST NOT add a Route header
10040cb5e5dSvi 	 * field to the request.
10140cb5e5dSvi 	 */
10240cb5e5dSvi 	(void) sip_delete_header_by_name(sip_msg, SIP_ROUTE);
10340cb5e5dSvi 
10440cb5e5dSvi 	if (_dialog->sip_dlg_route_set != NULL) {
10540cb5e5dSvi 		if (sip_copy_header(sip_msg, _dialog->sip_dlg_route_set,
10640cb5e5dSvi 		    NULL) != 0) {
10740cb5e5dSvi 			_dialog->sip_dlg_local_cseq = oldseq;
10840cb5e5dSvi 			goto err_ret;
10940cb5e5dSvi 		}
11040cb5e5dSvi 	}
11140cb5e5dSvi 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
11240cb5e5dSvi 	return (sip_msg);
11340cb5e5dSvi err_ret:
11440cb5e5dSvi 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
11540cb5e5dSvi 	sip_free_msg(sip_msg);
11640cb5e5dSvi 	return (NULL);
11740cb5e5dSvi }
11840cb5e5dSvi 
119df4705eaSgm /*
120df4705eaSgm  * Create a request using the state maintained in the dialog. The request will
121df4705eaSgm  * not have Contact header.
122df4705eaSgm  */
123df4705eaSgm sip_msg_t
sip_create_dialog_req_nocontact(sip_method_t method,sip_dialog_t dialog,char * transport,char * sent_by,int sent_by_port,char * via_param,uint32_t maxforward,int cseq)124df4705eaSgm sip_create_dialog_req_nocontact(sip_method_t method, sip_dialog_t dialog,
125df4705eaSgm     char *transport, char *sent_by, int sent_by_port, char *via_param,
126df4705eaSgm     uint32_t maxforward, int cseq)
127df4705eaSgm {
128df4705eaSgm 	sip_msg_t	sip_msg;
129df4705eaSgm 
130df4705eaSgm 	sip_msg = sip_create_dialog_req(method, dialog, transport, sent_by,
131df4705eaSgm 	    sent_by_port, via_param, maxforward, cseq);
132df4705eaSgm 	if (sip_msg != NULL) {
133df4705eaSgm 		if (sip_delete_header_by_name(sip_msg, SIP_CONTACT) != 0) {
134df4705eaSgm 			sip_free_msg(sip_msg);
135df4705eaSgm 			return (NULL);
136df4705eaSgm 		}
137df4705eaSgm 	}
138df4705eaSgm 
139df4705eaSgm 	return (sip_msg);
140df4705eaSgm }
141df4705eaSgm 
14240cb5e5dSvi /*
14340cb5e5dSvi  * Get the Dialog method
14440cb5e5dSvi  */
14540cb5e5dSvi int
sip_get_dialog_method(sip_dialog_t dialog,int * error)14640cb5e5dSvi sip_get_dialog_method(sip_dialog_t dialog, int *error)
14740cb5e5dSvi {
14840cb5e5dSvi 	_sip_dialog_t	*_dialog;
14940cb5e5dSvi 
15040cb5e5dSvi 	if (error != NULL)
15140cb5e5dSvi 		*error = 0;
15240cb5e5dSvi 	if (!sip_manage_dialog) {
15340cb5e5dSvi 		if (error != NULL)
15440cb5e5dSvi 			*error = EINVAL;
15540cb5e5dSvi 		return (0);
15640cb5e5dSvi 	}
15740cb5e5dSvi 	if (dialog == NULL) {
15840cb5e5dSvi 		if (error != NULL)
15940cb5e5dSvi 			*error = EINVAL;
16040cb5e5dSvi 		return (0);
16140cb5e5dSvi 	}
16240cb5e5dSvi 	_dialog = (_sip_dialog_t *)dialog;
16340cb5e5dSvi 	return (_dialog->sip_dlg_method);
16440cb5e5dSvi }
16540cb5e5dSvi 
16640cb5e5dSvi /*
16740cb5e5dSvi  * Get the Dialog state
16840cb5e5dSvi  */
16940cb5e5dSvi int
sip_get_dialog_state(sip_dialog_t dialog,int * error)17040cb5e5dSvi sip_get_dialog_state(sip_dialog_t dialog, int *error)
17140cb5e5dSvi {
17240cb5e5dSvi 	_sip_dialog_t	*_dialog;
17340cb5e5dSvi 
17440cb5e5dSvi 	if (error != NULL)
17540cb5e5dSvi 		*error = 0;
17640cb5e5dSvi 	if (!sip_manage_dialog) {
17740cb5e5dSvi 		if (error != NULL)
17840cb5e5dSvi 			*error = EINVAL;
17940cb5e5dSvi 		return (0);
18040cb5e5dSvi 	}
18140cb5e5dSvi 	if (dialog == NULL) {
18240cb5e5dSvi 		if (error != NULL)
18340cb5e5dSvi 			*error = EINVAL;
18440cb5e5dSvi 		return (0);
18540cb5e5dSvi 	}
18640cb5e5dSvi 	_dialog = (_sip_dialog_t *)dialog;
18740cb5e5dSvi 	return (_dialog->sip_dlg_state);
18840cb5e5dSvi }
18940cb5e5dSvi 
19040cb5e5dSvi /*
19140cb5e5dSvi  * Return the dialog callid
19240cb5e5dSvi  */
19340cb5e5dSvi const sip_str_t *
sip_get_dialog_callid(sip_dialog_t dialog,int * error)19440cb5e5dSvi sip_get_dialog_callid(sip_dialog_t dialog, int *error)
19540cb5e5dSvi {
19640cb5e5dSvi 	_sip_dialog_t		*_dialog;
19740cb5e5dSvi 	const struct sip_value	*val;
19840cb5e5dSvi 	const sip_str_t		*callid = NULL;
19940cb5e5dSvi 
20040cb5e5dSvi 	if (error != NULL)
20140cb5e5dSvi 		*error = 0;
20240cb5e5dSvi 	if (!sip_manage_dialog || dialog == NULL) {
20340cb5e5dSvi 		if (error != NULL)
20440cb5e5dSvi 			*error = EINVAL;
20540cb5e5dSvi 		return (NULL);
20640cb5e5dSvi 	}
20740cb5e5dSvi 	_dialog = (_sip_dialog_t *)dialog;
20840cb5e5dSvi 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
20940cb5e5dSvi 	if (dialog->sip_dlg_call_id != NULL) {
21040cb5e5dSvi 		val = sip_get_header_value(_dialog->sip_dlg_call_id, error);
21140cb5e5dSvi 		if (val == NULL) {
21240cb5e5dSvi 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
21340cb5e5dSvi 			return (NULL);
21440cb5e5dSvi 		}
21540cb5e5dSvi 		callid = &((sip_hdr_value_t *)val)->str_val;
21640cb5e5dSvi 	}
21740cb5e5dSvi 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
21840cb5e5dSvi 	return (callid);
21940cb5e5dSvi }
22040cb5e5dSvi 
22140cb5e5dSvi /*
22240cb5e5dSvi  * Return the dialog localtag.
22340cb5e5dSvi  */
22440cb5e5dSvi const sip_str_t *
sip_get_dialog_local_tag(sip_dialog_t dialog,int * error)22540cb5e5dSvi sip_get_dialog_local_tag(sip_dialog_t dialog, int *error)
22640cb5e5dSvi {
22740cb5e5dSvi 	_sip_dialog_t		*_dialog;
22840cb5e5dSvi 	const sip_str_t		*ltag = NULL;
22940cb5e5dSvi 	const struct sip_value	*val;
23040cb5e5dSvi 
23140cb5e5dSvi 	if (error != NULL)
23240cb5e5dSvi 		*error = 0;
23340cb5e5dSvi 	if (!sip_manage_dialog || dialog == NULL) {
23440cb5e5dSvi 		if (error != NULL)
23540cb5e5dSvi 			*error = EINVAL;
23640cb5e5dSvi 		return (NULL);
23740cb5e5dSvi 	}
23840cb5e5dSvi 	_dialog = (_sip_dialog_t *)dialog;
23940cb5e5dSvi 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
24040cb5e5dSvi 	if (dialog->sip_dlg_local_uri_tag != NULL) {
24140cb5e5dSvi 		val = sip_get_header_value(_dialog->sip_dlg_local_uri_tag,
24240cb5e5dSvi 		    error);
24340cb5e5dSvi 		if (val == NULL) {
24440cb5e5dSvi 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
24540cb5e5dSvi 			return (NULL);
24640cb5e5dSvi 		}
24740cb5e5dSvi 		ltag = sip_get_param_value((sip_header_value_t)val, "tag",
24840cb5e5dSvi 		    error);
24940cb5e5dSvi 	}
25040cb5e5dSvi 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
25140cb5e5dSvi 	return (ltag);
25240cb5e5dSvi }
25340cb5e5dSvi 
25440cb5e5dSvi /*
25540cb5e5dSvi  * Return the dialog remotetag
25640cb5e5dSvi  */
25740cb5e5dSvi const sip_str_t *
sip_get_dialog_remote_tag(sip_dialog_t dialog,int * error)25840cb5e5dSvi sip_get_dialog_remote_tag(sip_dialog_t dialog, int *error)
25940cb5e5dSvi {
26040cb5e5dSvi 	_sip_dialog_t		*_dialog;
26140cb5e5dSvi 	const sip_str_t		*ttag = NULL;
26240cb5e5dSvi 	const struct sip_value	*val;
26340cb5e5dSvi 
26440cb5e5dSvi 	if (error != NULL)
26540cb5e5dSvi 		*error = 0;
26640cb5e5dSvi 	if (!sip_manage_dialog || dialog == NULL) {
26740cb5e5dSvi 		if (error != NULL)
26840cb5e5dSvi 			*error = EINVAL;
26940cb5e5dSvi 		return (NULL);
27040cb5e5dSvi 	}
27140cb5e5dSvi 	_dialog = (_sip_dialog_t *)dialog;
27240cb5e5dSvi 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
27340cb5e5dSvi 	if (dialog->sip_dlg_remote_uri_tag != NULL) {
27440cb5e5dSvi 		val = sip_get_header_value(_dialog->sip_dlg_remote_uri_tag,
27540cb5e5dSvi 		    error);
27640cb5e5dSvi 		if (val == NULL) {
27740cb5e5dSvi 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
27840cb5e5dSvi 			return (NULL);
27940cb5e5dSvi 		}
28040cb5e5dSvi 		ttag = sip_get_param_value((sip_header_value_t)val, "tag",
28140cb5e5dSvi 		    error);
28240cb5e5dSvi 	}
28340cb5e5dSvi 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
28440cb5e5dSvi 
28540cb5e5dSvi 	return (ttag);
28640cb5e5dSvi }
28740cb5e5dSvi 
28840cb5e5dSvi /*
28940cb5e5dSvi  * Return the dialog localuri.
29040cb5e5dSvi  */
29140cb5e5dSvi const struct sip_uri *
sip_get_dialog_local_uri(sip_dialog_t dialog,int * error)29240cb5e5dSvi sip_get_dialog_local_uri(sip_dialog_t dialog, int *error)
29340cb5e5dSvi {
29440cb5e5dSvi 	_sip_dialog_t		*_dialog;
29540cb5e5dSvi 	const _sip_uri_t	*luri = NULL;
29640cb5e5dSvi 	const struct sip_value	*val;
29740cb5e5dSvi 
29840cb5e5dSvi 	if (error != NULL)
29940cb5e5dSvi 		*error = 0;
30040cb5e5dSvi 	if (!sip_manage_dialog || dialog == NULL) {
30140cb5e5dSvi 		if (error != NULL)
30240cb5e5dSvi 			*error = EINVAL;
30340cb5e5dSvi 		return (NULL);
30440cb5e5dSvi 	}
30540cb5e5dSvi 	_dialog = (_sip_dialog_t *)dialog;
30640cb5e5dSvi 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
30740cb5e5dSvi 	if (dialog->sip_dlg_local_uri_tag != NULL) {
30840cb5e5dSvi 		val = sip_get_header_value(_dialog->sip_dlg_local_uri_tag,
30940cb5e5dSvi 		    error);
31040cb5e5dSvi 		if (val == NULL) {
31140cb5e5dSvi 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
31240cb5e5dSvi 			return (NULL);
31340cb5e5dSvi 		}
31440cb5e5dSvi 		luri = val->sip_value_parse_uri;
31540cb5e5dSvi 	}
31640cb5e5dSvi 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
31740cb5e5dSvi 
31840cb5e5dSvi 	return ((sip_uri_t)luri);
31940cb5e5dSvi }
32040cb5e5dSvi 
32140cb5e5dSvi /*
32240cb5e5dSvi  * Return the dialog remoteuri.
32340cb5e5dSvi  */
32440cb5e5dSvi const struct sip_uri *
sip_get_dialog_remote_uri(sip_dialog_t dialog,int * error)32540cb5e5dSvi sip_get_dialog_remote_uri(sip_dialog_t dialog, int *error)
32640cb5e5dSvi {
32740cb5e5dSvi 	_sip_dialog_t		*_dialog;
32840cb5e5dSvi 	const _sip_uri_t	*ruri = NULL;
32940cb5e5dSvi 	const struct sip_value	*val;
33040cb5e5dSvi 
33140cb5e5dSvi 	if (error != NULL)
33240cb5e5dSvi 		*error = 0;
33340cb5e5dSvi 	if (!sip_manage_dialog || dialog == NULL) {
33440cb5e5dSvi 		if (error != NULL)
33540cb5e5dSvi 			*error = EINVAL;
33640cb5e5dSvi 		return (NULL);
33740cb5e5dSvi 	}
33840cb5e5dSvi 	_dialog = (_sip_dialog_t *)dialog;
33940cb5e5dSvi 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
34040cb5e5dSvi 	if (dialog->sip_dlg_remote_uri_tag != NULL) {
34140cb5e5dSvi 		val = sip_get_header_value(dialog->sip_dlg_remote_uri_tag,
34240cb5e5dSvi 		    error);
34340cb5e5dSvi 		if (val == NULL) {
34440cb5e5dSvi 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
34540cb5e5dSvi 			return (NULL);
34640cb5e5dSvi 		}
34740cb5e5dSvi 		ruri = val->sip_value_parse_uri;
34840cb5e5dSvi 	}
34940cb5e5dSvi 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
35040cb5e5dSvi 	return ((sip_uri_t)ruri);
35140cb5e5dSvi }
35240cb5e5dSvi 
35340cb5e5dSvi /*
35440cb5e5dSvi  * Return the dialog remotetarg.
35540cb5e5dSvi  */
35640cb5e5dSvi const struct sip_uri *
sip_get_dialog_remote_target_uri(sip_dialog_t dialog,int * error)35740cb5e5dSvi sip_get_dialog_remote_target_uri(sip_dialog_t dialog, int *error)
35840cb5e5dSvi {
35940cb5e5dSvi 	_sip_dialog_t		*_dialog;
36040cb5e5dSvi 	const struct sip_uri	*rtarg = NULL;
36140cb5e5dSvi 	const struct sip_value	*val;
36240cb5e5dSvi 
36340cb5e5dSvi 	if (error != NULL)
36440cb5e5dSvi 		*error = 0;
36540cb5e5dSvi 	if (!sip_manage_dialog || dialog == NULL) {
36640cb5e5dSvi 		if (error != NULL)
36740cb5e5dSvi 			*error = EINVAL;
36840cb5e5dSvi 		return (NULL);
36940cb5e5dSvi 	}
37040cb5e5dSvi 	_dialog = (_sip_dialog_t *)dialog;
37140cb5e5dSvi 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
37240cb5e5dSvi 	if (dialog->sip_dlg_remote_target != NULL) {
37340cb5e5dSvi 		val = sip_get_header_value(_dialog->sip_dlg_remote_target,
37440cb5e5dSvi 		    error);
37540cb5e5dSvi 		if (val == NULL) {
37640cb5e5dSvi 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
37740cb5e5dSvi 			return (NULL);
37840cb5e5dSvi 		}
37940cb5e5dSvi 		rtarg = val->sip_value_parse_uri;
38040cb5e5dSvi 	}
38140cb5e5dSvi 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
38240cb5e5dSvi 
38340cb5e5dSvi 	return ((sip_uri_t)rtarg);
38440cb5e5dSvi }
38540cb5e5dSvi 
386df4705eaSgm /*
387df4705eaSgm  * Return the dialog local contact uri.
388df4705eaSgm  */
389df4705eaSgm const struct sip_uri *
sip_get_dialog_local_contact_uri(sip_dialog_t dialog,int * error)390df4705eaSgm sip_get_dialog_local_contact_uri(sip_dialog_t dialog, int *error)
391df4705eaSgm {
392df4705eaSgm 	_sip_dialog_t		*_dialog;
393df4705eaSgm 	const struct sip_uri	*lcuri = NULL;
394df4705eaSgm 	const struct sip_value	*val;
395df4705eaSgm 
396df4705eaSgm 	if (error != NULL)
397df4705eaSgm 		*error = 0;
398df4705eaSgm 	if (!sip_manage_dialog || dialog == NULL) {
399df4705eaSgm 		if (error != NULL)
400df4705eaSgm 			*error = EINVAL;
401df4705eaSgm 		return (NULL);
402df4705eaSgm 	}
403df4705eaSgm 	_dialog = (_sip_dialog_t *)dialog;
404df4705eaSgm 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
405df4705eaSgm 	if (dialog->sip_dlg_local_contact != NULL) {
406df4705eaSgm 		val = sip_get_header_value(_dialog->sip_dlg_local_contact,
407df4705eaSgm 		    error);
408df4705eaSgm 		if (val == NULL) {
409df4705eaSgm 			(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
410df4705eaSgm 			return (NULL);
411df4705eaSgm 		}
412df4705eaSgm 		lcuri = val->sip_value_parse_uri;
413df4705eaSgm 	}
414df4705eaSgm 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
415df4705eaSgm 
416df4705eaSgm 	return ((sip_uri_t)lcuri);
417df4705eaSgm }
418df4705eaSgm 
41940cb5e5dSvi /*
42040cb5e5dSvi  * Return the dialog route set
42140cb5e5dSvi  */
42240cb5e5dSvi const sip_str_t *
sip_get_dialog_route_set(sip_dialog_t dialog,int * error)42340cb5e5dSvi sip_get_dialog_route_set(sip_dialog_t dialog, int *error)
42440cb5e5dSvi {
42540cb5e5dSvi 	_sip_dialog_t		*_dialog;
42640cb5e5dSvi 
42740cb5e5dSvi 	if (error != NULL)
42840cb5e5dSvi 		*error = 0;
42940cb5e5dSvi 	if (!sip_manage_dialog || dialog == NULL) {
43040cb5e5dSvi 		if (error != NULL)
43140cb5e5dSvi 			*error = EINVAL;
43240cb5e5dSvi 		return (NULL);
43340cb5e5dSvi 	}
43440cb5e5dSvi 	_dialog = (_sip_dialog_t *)dialog;
43540cb5e5dSvi 	if (_dialog->sip_dlg_rset.sip_str_len > 0)
43640cb5e5dSvi 		return (&_dialog->sip_dlg_rset);
43740cb5e5dSvi 	return (NULL);
43840cb5e5dSvi }
43940cb5e5dSvi 
44040cb5e5dSvi /*
44140cb5e5dSvi  * Return the dialog secure
44240cb5e5dSvi  */
44340cb5e5dSvi boolean_t
sip_is_dialog_secure(sip_dialog_t dialog,int * error)44440cb5e5dSvi sip_is_dialog_secure(sip_dialog_t dialog, int *error)
44540cb5e5dSvi {
44640cb5e5dSvi 	_sip_dialog_t	*_dialog;
44740cb5e5dSvi 	boolean_t	issecure;
44840cb5e5dSvi 
44940cb5e5dSvi 	if (error != NULL)
45040cb5e5dSvi 		*error = 0;
45140cb5e5dSvi 	if (!sip_manage_dialog || dialog == NULL) {
45240cb5e5dSvi 		if (error != NULL)
45340cb5e5dSvi 			*error = EINVAL;
45440cb5e5dSvi 		return (B_FALSE);
45540cb5e5dSvi 	}
45640cb5e5dSvi 	_dialog = (_sip_dialog_t *)dialog;
45740cb5e5dSvi 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
45840cb5e5dSvi 	issecure = _dialog->sip_dlg_secure;
45940cb5e5dSvi 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
46040cb5e5dSvi 	return (issecure);
46140cb5e5dSvi }
46240cb5e5dSvi 
46340cb5e5dSvi /*
46440cb5e5dSvi  * Return the dialog local cseq
46540cb5e5dSvi  */
46640cb5e5dSvi uint32_t
sip_get_dialog_local_cseq(sip_dialog_t dialog,int * error)46740cb5e5dSvi sip_get_dialog_local_cseq(sip_dialog_t dialog, int *error)
46840cb5e5dSvi {
46940cb5e5dSvi 	_sip_dialog_t	*_dialog;
47040cb5e5dSvi 	uint32_t	cseq;
47140cb5e5dSvi 
47240cb5e5dSvi 	if (error != NULL)
47340cb5e5dSvi 		*error = 0;
47440cb5e5dSvi 	if (!sip_manage_dialog || dialog == NULL) {
47540cb5e5dSvi 		if (error != NULL)
47640cb5e5dSvi 			*error = EINVAL;
47740cb5e5dSvi 		return (0);
47840cb5e5dSvi 	}
47940cb5e5dSvi 	_dialog = (_sip_dialog_t *)dialog;
48040cb5e5dSvi 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
48140cb5e5dSvi 	cseq = _dialog->sip_dlg_local_cseq;
48240cb5e5dSvi 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
48340cb5e5dSvi 	return (cseq);
48440cb5e5dSvi }
48540cb5e5dSvi 
48640cb5e5dSvi /*
48740cb5e5dSvi  * Return the dialog remote cseq
48840cb5e5dSvi  */
48940cb5e5dSvi uint32_t
sip_get_dialog_remote_cseq(sip_dialog_t dialog,int * error)49040cb5e5dSvi sip_get_dialog_remote_cseq(sip_dialog_t dialog, int *error)
49140cb5e5dSvi {
49240cb5e5dSvi 	_sip_dialog_t	*_dialog;
49340cb5e5dSvi 	uint32_t	cseq;
49440cb5e5dSvi 
49540cb5e5dSvi 	if (error != NULL)
49640cb5e5dSvi 		*error = 0;
49740cb5e5dSvi 	if (!sip_manage_dialog || dialog == NULL) {
49840cb5e5dSvi 		if (error != NULL)
49940cb5e5dSvi 			*error = EINVAL;
50040cb5e5dSvi 		return (0);
50140cb5e5dSvi 	}
50240cb5e5dSvi 	_dialog = (_sip_dialog_t *)dialog;
50340cb5e5dSvi 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
50440cb5e5dSvi 	cseq = _dialog->sip_dlg_remote_cseq;
50540cb5e5dSvi 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
50640cb5e5dSvi 	return (cseq);
50740cb5e5dSvi }
50840cb5e5dSvi 
50940cb5e5dSvi /*
51040cb5e5dSvi  * Return the dialog type
51140cb5e5dSvi  */
51240cb5e5dSvi int
sip_get_dialog_type(sip_dialog_t dialog,int * error)51340cb5e5dSvi sip_get_dialog_type(sip_dialog_t dialog, int *error)
51440cb5e5dSvi {
51540cb5e5dSvi 	_sip_dialog_t	*_dialog;
51640cb5e5dSvi 	int		type;
51740cb5e5dSvi 
51840cb5e5dSvi 	if (error != NULL)
51940cb5e5dSvi 		*error = 0;
52040cb5e5dSvi 	if (!sip_manage_dialog || dialog == NULL) {
52140cb5e5dSvi 		if (error != NULL)
52240cb5e5dSvi 			*error = EINVAL;
52340cb5e5dSvi 		return (-1);
52440cb5e5dSvi 	}
52540cb5e5dSvi 	_dialog = (_sip_dialog_t *)dialog;
52640cb5e5dSvi 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
52740cb5e5dSvi 	type = _dialog->sip_dlg_type;
52840cb5e5dSvi 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
52940cb5e5dSvi 	return (type);
53040cb5e5dSvi }
53140cb5e5dSvi 
532*943efbc3Sgm /*
533*943efbc3Sgm  * Return the number of messages exchanged within a dialog.
534*943efbc3Sgm  */
535*943efbc3Sgm int
sip_get_dialog_msgcnt(sip_dialog_t dialog,int * error)536*943efbc3Sgm sip_get_dialog_msgcnt(sip_dialog_t dialog, int *error)
537*943efbc3Sgm {
538*943efbc3Sgm 	_sip_dialog_t	*_dialog;
539*943efbc3Sgm 	int		nmsgs;
540*943efbc3Sgm 
541*943efbc3Sgm 	if (error != NULL)
542*943efbc3Sgm 		*error = 0;
543*943efbc3Sgm 	if (!sip_manage_dialog || dialog == NULL) {
544*943efbc3Sgm 		if (error != NULL)
545*943efbc3Sgm 			*error = EINVAL;
546*943efbc3Sgm 		return (-1);
547*943efbc3Sgm 	}
548*943efbc3Sgm 	_dialog = (_sip_dialog_t *)dialog;
549*943efbc3Sgm 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
550*943efbc3Sgm 	nmsgs = _dialog->sip_dlg_msgcnt;
551*943efbc3Sgm 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
552*943efbc3Sgm 	return (nmsgs);
553*943efbc3Sgm }
55440cb5e5dSvi 
55540cb5e5dSvi /*
55640cb5e5dSvi  * Partial dialog ?
55740cb5e5dSvi  */
55840cb5e5dSvi boolean_t
sip_incomplete_dialog(sip_dialog_t dialog)55940cb5e5dSvi sip_incomplete_dialog(sip_dialog_t dialog)
56040cb5e5dSvi {
56140cb5e5dSvi 	_sip_dialog_t	*_dialog;
56240cb5e5dSvi 	boolean_t	isnew;
56340cb5e5dSvi 
56440cb5e5dSvi 	if (!sip_manage_dialog || dialog == NULL)
56540cb5e5dSvi 		return (B_FALSE);
56640cb5e5dSvi 	_dialog = (_sip_dialog_t *)dialog;
56740cb5e5dSvi 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
56840cb5e5dSvi 	isnew = _dialog->sip_dlg_state == SIP_DLG_NEW;
56940cb5e5dSvi 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
57040cb5e5dSvi 	return (isnew);
57140cb5e5dSvi }
57240cb5e5dSvi 
57340cb5e5dSvi /*
57440cb5e5dSvi  * Hold dialog
57540cb5e5dSvi  */
57640cb5e5dSvi void
sip_hold_dialog(sip_dialog_t dialog)57740cb5e5dSvi sip_hold_dialog(sip_dialog_t dialog)
57840cb5e5dSvi {
57940cb5e5dSvi 	_sip_dialog_t	*_dialog;
58040cb5e5dSvi 
58140cb5e5dSvi 	if (!sip_manage_dialog || dialog == NULL)
58240cb5e5dSvi 		return;
58340cb5e5dSvi 	_dialog = (_sip_dialog_t *)dialog;
58440cb5e5dSvi 	(void) pthread_mutex_lock(&_dialog->sip_dlg_mutex);
58540cb5e5dSvi 	SIP_DLG_REFCNT_INCR(_dialog);
58640cb5e5dSvi 	(void) pthread_mutex_unlock(&_dialog->sip_dlg_mutex);
58740cb5e5dSvi }
58840cb5e5dSvi 
58940cb5e5dSvi /*
59040cb5e5dSvi  * Release dialog
59140cb5e5dSvi  */
59240cb5e5dSvi void
sip_release_dialog(sip_dialog_t dialog)59340cb5e5dSvi sip_release_dialog(sip_dialog_t dialog)
59440cb5e5dSvi {
59540cb5e5dSvi 	_sip_dialog_t	*_dialog;
59640cb5e5dSvi 
59740cb5e5dSvi 	if (!sip_manage_dialog || dialog == NULL)
59840cb5e5dSvi 		return;
59940cb5e5dSvi 	_dialog = (_sip_dialog_t *)dialog;
60040cb5e5dSvi 	SIP_DLG_REFCNT_DECR(_dialog);
60140cb5e5dSvi }
60240cb5e5dSvi 
60340cb5e5dSvi /*
60440cb5e5dSvi  * Delete a dialog
60540cb5e5dSvi  */
60640cb5e5dSvi void
sip_delete_dialog(sip_dialog_t dialog)60740cb5e5dSvi sip_delete_dialog(sip_dialog_t dialog)
60840cb5e5dSvi {
60940cb5e5dSvi 	if (!sip_manage_dialog || dialog == NULL)
61040cb5e5dSvi 		return;
61140cb5e5dSvi 	sip_dialog_terminate(dialog, NULL);
61240cb5e5dSvi }
613