⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sip_dialog.c

📁 VoIP use SIP protocol interface
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END *//* * Copyright 2006 Sun Microsystems, Inc.  All rights reserved. * Use is subject to license terms. */#pragma ident	"@(#)sip_dialog.c	1.28	06/08/16 SMI"#include "sip_msg.h"#include "sip_hash.h"#include "sip_dialog.h"#include "sip_miscdefs.h"#include "sip_parse_generic.h"#define	SIP_DLG_XCHG_FROM	0#define	SIP_DLG_XCHG_TO		1/* Dialog state change callback function */void (*sip_dlg_ulp_state_cb)(sip_dialog_t, sip_msg_t, int, int) = NULL;boolean_t	sip_incomplete_dialog(sip_dialog_t);/* Exchange From/To header */_sip_header_t *sip_dlg_xchg_from_to(sip_msg_t, int);/* Complete dialog hash table */sip_hash_t sip_dialog_hash[SIP_HASH_SZ];/* Partial dialog hash table */sip_hash_t sip_dialog_phash[SIP_HASH_SZ];/* Route set structure */typedef struct sip_dlg_route_set_s  {	char		*sip_dlg_route;	sip_str_t	sip_dlg_ruri;	boolean_t	sip_dlg_route_lr;	struct sip_dlg_route_set_s *sip_dlg_route_next;}sip_dlg_route_set_t;sip_dialog_t		sip_seed_dialog(sip_conn_object_t, _sip_msg_t *,			    void (*func)(sip_dialog_t, sip_msg_t, void *),			    boolean_t, int);sip_dialog_t		sip_complete_dialog(_sip_msg_t *, _sip_dialog_t *,			    void (*func)(sip_dialog_t, sip_msg_t, void *));sip_dialog_t		sip_dialog_create(_sip_msg_t *, _sip_msg_t *, int);int			sip_dialog_process(_sip_msg_t *, sip_dialog_t *,			    void (*func)(sip_dialog_t, sip_msg_t, void *));void			sip_dialog_delete(_sip_dialog_t *);void			sip_dialog_init();sip_dialog_t		sip_dialog_find(_sip_msg_t *);boolean_t		sip_dialog_match(void *, void *);boolean_t		sip_dialog_free(void *, void *, int *);sip_dialog_t		sip_update_dialog(sip_dialog_t, _sip_msg_t *,			    void (*func)(sip_dialog_t, sip_msg_t, void *));char			*sip_dialog_req_uri(sip_dialog_t);static void		sip_release_dialog_res(_sip_dialog_t *);void			sip_dlg_self_destruct(void *);static int		sip_dialog_get_route_set(_sip_dialog_t *, _sip_msg_t *,			    int);static void		sip_dialog_free_rset(sip_dlg_route_set_t *);/* Timer object for partial dialogs */typedef struct sip_dialog_timer_obj_s {	_sip_dialog_t	*dialog;	void		(*func)(sip_dialog_t, sip_msg_t, void *);} sip_dialog_timer_obj_t;/* To avoid duplication all over the place */static voidsip_release_dialog_res(_sip_dialog_t *dialog){	assert(dialog->sip_dlg_ref_cnt == 0);	if (SIP_IS_TIMER_RUNNING(dialog->sip_dlg_timer))		SIP_CANCEL_TIMER(dialog->sip_dlg_timer);	if (dialog->sip_dlg_call_id != NULL)		sip_free_header(dialog->sip_dlg_call_id);	if (dialog->sip_dlg_local_uri_tag != NULL)		sip_free_header(dialog->sip_dlg_local_uri_tag);	if (dialog->sip_dlg_remote_uri_tag != NULL)		sip_free_header(dialog->sip_dlg_remote_uri_tag);	if (dialog->sip_dlg_remote_target != NULL)		sip_free_header(dialog->sip_dlg_remote_target);	if (dialog->sip_dlg_route_set != NULL)		sip_free_header(dialog->sip_dlg_route_set);	if (dialog->sip_dlg_event != NULL)		sip_free_header(dialog->sip_dlg_event);	if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) {		free(dialog->sip_dlg_req_uri.sip_str_ptr);		dialog->sip_dlg_req_uri.sip_str_ptr = NULL;		dialog->sip_dlg_req_uri.sip_str_len = 0;	}	if (dialog->sip_dlg_rset.sip_str_ptr != NULL) {		free(dialog->sip_dlg_rset.sip_str_ptr);		dialog->sip_dlg_rset.sip_str_len = 0;		dialog->sip_dlg_rset.sip_str_ptr = NULL;	}	(void) pthread_mutex_destroy(&dialog->sip_dlg_mutex);	free(dialog);}/* * Get the route information from the 'value' and add it to the route * set. */static sip_dlg_route_set_t *sip_add_route_to_set(sip_hdr_value_t *value){	int			vlen = 0;	sip_dlg_route_set_t	*rset;	char			*crlf;	const sip_param_t	*uri_param;	int			error;	rset = calloc(1, sizeof (*rset));	if (rset == NULL)		return (NULL);	rset->sip_dlg_route_next = NULL;	vlen = value->sip_value_end - value->sip_value_start;	/* check for CRLF */	crlf = value->sip_value_end - strlen(SIP_CRLF);	while (crlf != NULL && strncmp(crlf, SIP_CRLF, strlen(SIP_CRLF)) == 0) {		vlen -= strlen(SIP_CRLF);		crlf -= strlen(SIP_CRLF);	}	rset->sip_dlg_route = calloc(1, vlen + 1);	if (rset->sip_dlg_route == NULL) {		free(rset);		return (NULL);	}	/* loose routing */	rset->sip_dlg_route_lr = B_FALSE;	(void) strncpy(rset->sip_dlg_route, value->sip_value_start, vlen);	rset->sip_dlg_ruri.sip_str_ptr = rset->sip_dlg_route +	    (value->cftr_uri.sip_str_ptr - value->sip_value_start);	rset->sip_dlg_ruri.sip_str_len = value->cftr_uri.sip_str_len;	rset->sip_dlg_route[vlen] = '\0';	assert(value->sip_value_parsed_uri != NULL);	/*	 * Check if the 'lr' param is present for this route.	 */	uri_param = sip_get_uri_params(value->sip_value_parsed_uri, &error);	if (error != 0) {		free(rset->sip_dlg_route);		free(rset);		return (NULL);	}	if (uri_param != NULL) {		rset->sip_dlg_route_lr = sip_is_param_present(uri_param, "lr",		    strlen("lr"));	}	return (rset);}/* * Depending on the route-set, determine the request URI. */char *sip_dialog_req_uri(sip_dialog_t dialog){	const sip_str_t		*req_uri;	char			*uri;	_sip_dialog_t		*_dialog;	_dialog = (_sip_dialog_t *)dialog;	if (_dialog->sip_dlg_route_set == NULL ||	    _dialog->sip_dlg_req_uri.sip_str_ptr == NULL) {		const struct sip_value	*val;		val = sip_get_header_value(_dialog->sip_dlg_remote_target,		    NULL);		req_uri = &((sip_hdr_value_t *)val)->cftr_uri;	} else {		req_uri = &_dialog->sip_dlg_req_uri;	}	uri = (char *)malloc(req_uri->sip_str_len + 1);	if (uri == NULL)		return (NULL);	(void) strncpy(uri, req_uri->sip_str_ptr, req_uri->sip_str_len);	uri[req_uri->sip_str_len] = '\0';	return (uri);}/* Free the route set. */voidsip_dialog_free_rset(sip_dlg_route_set_t *rset){	sip_dlg_route_set_t	*next;	while (rset != NULL) {		next = rset->sip_dlg_route_next;		rset->sip_dlg_route_next = NULL;		free(rset->sip_dlg_route);		free(rset);		rset = next;	}}/* Recompute route-set */static intsip_dlg_recompute_rset(_sip_dialog_t *dialog, _sip_msg_t *sip_msg, int what){	int ret;	if (dialog->sip_dlg_route_set != NULL) {		sip_free_header(dialog->sip_dlg_route_set);		dialog->sip_dlg_route_set = NULL;	}	if (dialog->sip_dlg_req_uri.sip_str_ptr != NULL) {		free(dialog->sip_dlg_req_uri.sip_str_ptr);		dialog->sip_dlg_req_uri.sip_str_ptr = NULL;		dialog->sip_dlg_req_uri.sip_str_len = 0;	}	if (dialog->sip_dlg_rset.sip_str_ptr != NULL) {		free(dialog->sip_dlg_rset.sip_str_ptr);		dialog->sip_dlg_rset.sip_str_ptr = NULL;		dialog->sip_dlg_rset.sip_str_len = 0;	}	ret = sip_dialog_get_route_set(dialog, sip_msg, what);	return (ret);}/* * If the route set is empty, the UAC MUST place the remote target URI * into the Request-URI.  The UAC MUST NOT add a Route header field to * the request. * * If the route set is not empty, and the first URI in the route set * contains the lr parameter (see Section 19.1.1), the UAC MUST place * the remote target URI into the Request-URI and MUST include a Route * header field containing the route set values in order, including all * parameters. * * If the route set is not empty, and its first URI does not contain the * lr parameter, the UAC MUST place the first URI from the route set * into the Request-URI, stripping any parameters that are not allowed * in a Request-URI.  The UAC MUST add a Route header field containing * the remainder of the route set values in order, including all * parameters.  The UAC MUST then place the remote target URI into the * Route header field as the last value. */intsip_dialog_set_route_hdr(_sip_dialog_t *dialog, sip_dlg_route_set_t *rset_head,    int rcnt, int rlen){	size_t			rset_len;	_sip_header_t		*rhdr;	char			*rset;	char			*rp;	char			*rsp;	int			count;	sip_dlg_route_set_t	*route;	boolean_t		first = B_TRUE;	const sip_str_t		*to_uri;	char			*uri = NULL;	int			rspl;	int			rpl;	assert(rcnt > 0);	dialog->sip_dlg_rset.sip_str_len = rlen + rcnt - 1;	dialog->sip_dlg_rset.sip_str_ptr = malloc(rlen + rcnt);	if (dialog->sip_dlg_rset.sip_str_ptr == NULL)		return (ENOMEM);	rsp = dialog->sip_dlg_rset.sip_str_ptr;	rspl = rlen + rcnt;	route = rset_head;	rset_len = rlen;	if (!route->sip_dlg_route_lr) {		const struct sip_value	*val;		val = sip_get_header_value(dialog->sip_dlg_remote_target, NULL);		to_uri = &((sip_hdr_value_t *)val)->cftr_uri;		uri = (char *)malloc(to_uri->sip_str_len + 1);		if (uri == NULL) {			free(dialog->sip_dlg_rset.sip_str_ptr);			dialog->sip_dlg_rset.sip_str_len = 0;			dialog->sip_dlg_rset.sip_str_ptr = NULL;			return (ENOMEM);		}		(void) strncpy(uri, to_uri->sip_str_ptr, to_uri->sip_str_len);		uri[to_uri->sip_str_len] = '\0';		rset_len = rlen - strlen(route->sip_dlg_route) + strlen(uri) +		    SIP_SPACE + sizeof (char) + SIP_SPACE + sizeof (char);		count = snprintf(rsp, rspl, "%s", route->sip_dlg_route);		dialog->sip_dlg_req_uri.sip_str_ptr = malloc(		    route->sip_dlg_ruri.sip_str_len + 1);		if (dialog->sip_dlg_req_uri.sip_str_ptr == NULL) {			free(uri);			free(dialog->sip_dlg_rset.sip_str_ptr);			dialog->sip_dlg_rset.sip_str_len = 0;			dialog->sip_dlg_rset.sip_str_ptr = NULL;			return (ENOMEM);		}		(void) strncpy(dialog->sip_dlg_req_uri.sip_str_ptr, rsp +		    (route->sip_dlg_ruri.sip_str_ptr - route->sip_dlg_route),		    route->sip_dlg_ruri.sip_str_len);		dialog->sip_dlg_req_uri.sip_str_ptr[		    route->sip_dlg_ruri.sip_str_len] = '\0';		dialog->sip_dlg_req_uri.sip_str_len =		    route->sip_dlg_ruri.sip_str_len;		rsp += count;		rspl -= count;		route = route->sip_dlg_route_next;	}	/* rcnt - 1 is for the number of COMMAs */	rset_len += strlen(SIP_ROUTE) + SIP_SPACE + sizeof (char) + SIP_SPACE +	    rcnt - 1;	rset = malloc(rset_len + 1);	if (rset == NULL) {		free(dialog->sip_dlg_rset.sip_str_ptr);		dialog->sip_dlg_rset.sip_str_len = 0;		dialog->sip_dlg_rset.sip_str_ptr = NULL;		return (ENOMEM);	}	rhdr = sip_new_header(rset_len + strlen(SIP_CRLF));	if (rhdr == NULL) {		free(rset);		free(dialog->sip_dlg_rset.sip_str_ptr);		dialog->sip_dlg_rset.sip_str_len = 0;		dialog->sip_dlg_rset.sip_str_ptr = NULL;		return (ENOMEM);	}	rp = rset;	rpl = rset_len + 1;	count = snprintf(rp, rpl, "%s %c ", SIP_ROUTE, SIP_HCOLON);	rp += count;	rpl -= count;	while (route != NULL) {		if (first) {			count = snprintf(rp, rpl, "%s", route->sip_dlg_route);			rp += count;			rpl -= count;			first = B_FALSE;			if (uri != NULL) {				count = snprintf(rsp, rspl, "%c%s",				    SIP_COMMA, route->sip_dlg_route);			} else {				count = snprintf(rsp, rspl, "%s",				    route->sip_dlg_route);			}			rsp += count;			rspl -= count;		} else {			count = snprintf(rp, rpl, "%c%s", SIP_COMMA,			    route->sip_dlg_route);			rp += count;			rpl -= count;			count = snprintf(rsp, rspl, "%c%s", SIP_COMMA,			    route->sip_dlg_route);			rsp += count;			rspl -= count;		}		route = route->sip_dlg_route_next;	}	assert(rsp <= dialog->sip_dlg_rset.sip_str_ptr +	    dialog->sip_dlg_rset.sip_str_len);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -