Home | History | Annotate | Download | only in common
      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  */
     43 sip_msg_t
     44 sip_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);
    115 err_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  */
    125 sip_msg_t
    126 sip_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  */
    147 int
    148 sip_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  */
    171 int
    172 sip_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  */
    195 const sip_str_t *
    196 sip_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  */
    226 const sip_str_t *
    227 sip_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  */
    259 const sip_str_t *
    260 sip_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  */
    293 const struct sip_uri *
    294 sip_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  */
    326 const struct sip_uri *
    327 sip_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  */
    358 const struct sip_uri *
    359 sip_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  */
    391 const struct sip_uri *
    392 sip_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  */
    424 const sip_str_t *
    425 sip_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  */
    445 boolean_t
    446 sip_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  */
    468 uint32_t
    469 sip_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  */
    491 uint32_t
    492 sip_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  */
    514 int
    515 sip_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  */
    537 int
    538 sip_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  */
    560 boolean_t
    561 sip_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  */
    578 void
    579 sip_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  */
    594 void
    595 sip_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  */
    608 void
    609 sip_delete_dialog(sip_dialog_t dialog)
    610 {
    611 	if (!sip_manage_dialog || dialog == NULL)
    612 		return;
    613 	sip_dialog_terminate(dialog, NULL);
    614 }
    615