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 */
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 * Create a request using the state maintained in the dialog. The request will
123 * not have Contact header.
124 */
125sip_msg_t
126sip_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 */
147int
148sip_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 */
171int
172sip_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 */
195const sip_str_t *
196sip_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 */
226const sip_str_t *
227sip_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 */
259const sip_str_t *
260sip_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 */
293const struct sip_uri *
294sip_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 */
326const struct sip_uri *
327sip_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 */
358const struct sip_uri *
359sip_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 */
391const struct sip_uri *
392sip_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 */
424const sip_str_t *
425sip_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 */
445boolean_t
446sip_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 */
468uint32_t
469sip_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 */
491uint32_t
492sip_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 */
514int
515sip_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 */
537int
538sip_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 */
560boolean_t
561sip_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 */
578void
579sip_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 */
594void
595sip_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 */
608void
609sip_delete_dialog(sip_dialog_t dialog)
610{
611	if (!sip_manage_dialog || dialog == NULL)
612		return;
613	sip_dialog_terminate(dialog, NULL);
614}
615